package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.Response;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.gts.bpaas.middleware.cache.api.CacheManager;
import com.aliyun.gts.delivery.enterprise.sdk.orgaccount.out.OrganizationInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.*;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.event.ActivityJumpEvent;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.*;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.OrgAccountServiceAdapter;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.SyncProcessTaskProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.SyncTaskTracePostProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.UserInfoHandleProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.*;
import com.iwhalecloud.citybrain.flow.platform.manager.common.CheckResult;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ConstanceVariable;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.*;
import com.iwhalecloud.citybrain.flow.platform.manager.common.utils.UUIDGenerator;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.CommentTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.MsgTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.MultiInstanceKeyEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.NoticeTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowFormExternalInstanceDO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.factory.NodeCompletionConditionFactory;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.FormInstanceDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.model.NextNodeAssigneeTaskDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.model.NextNodeCandidateTaskDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.model.NodeAuthVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.TaskTraceQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.notice.FlowNoticeTemplateVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.user.UserMeta;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.CandidateEntity;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.OrgInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.UserInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.userentity.UserRelationShip;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.*;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.common.exception.BusiException;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.*;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.common.api.FlowableTaskAlreadyClaimedException;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.service.impl.persistence.entity.IdentityLinkEntity;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.iwhalecloud.citybrain.flow.platform.manager.common.ConstanceVariable.MUST_EXPRESS;
import static com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode.PARAM_NOT_EXIST;

/**
 * @author cheng.huaxing
 * @date 2019-02-01
 */
@Service
public class FlowTaskServiceImpl extends BaseProcessService implements FlowTaskService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FlowTaskInstApproverRepository flowTaskInstApproverRepository;

    @Autowired
    private FlowTaskTraceRepository flowTaskTraceRepository;

    @Autowired
    private FlowMultiInstanceTaskTraceRepository flowMultiInstanceTaskTraceRepository;

    @Autowired
    private FlowTaskTraceDAO flowTaskTraceDAO;

    @Autowired
    private FlowVarExpressionDAO flowVarExpressionDAO;

    @Autowired
    private FlowRuTimeoutSettingDAO flowRuTimeoutSettingDAO;

    @Autowired(required = false)
    private CacheManager cacheManager;
    @Autowired
    private FlowNoticeTemplateRepository flowNoticeTemplateRepository;

    @Autowired
    private FlowProcessInstanceTraceRepository processInstanceTraceRepository;

    @Autowired
    private FlowFormInstanceRepository formInstanceRepository;

    @Autowired
    private FormInstanceDraftRepository formInstanceDraftRepository;

    @Autowired
    private FlowFormRepository flowFormRepository;

    @Autowired
    private OrgAccountServiceAdapter orgAccountService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    FlowFormExternalInstanceDAO flowFormExternalInstanceDAO;

    @Autowired
    private FlowTaskTraceRepository taskTraceService;

    @Autowired
    private NodeCompletionConditionFactory nodeCompletionConditionFactory;

    @Autowired
    private FlowTaskCandidateSettingsRepository flowTaskCandidateSettingsRepository;

    @Autowired
    private UserGroupService userGroupService;

    @Autowired
    private UserPositionService userPositionService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserRelationShipService userRelationShipService;

    @Autowired
    private UserCustomFunctionService userCustomFunctionService;

    @Autowired
    private UserInfoHandleProcessor userInfoHandleProcessor;

    @Autowired
    private FlowRollbackService rollbackService;

    @Autowired
    private UserService userService;

    @Autowired
    private FlowBaseDataHandleProcessor flowBaseDataHandleProcessor;

    @Autowired
    private FlowProcessInstanceTraceRepository flowProcessInstanceTraceRepository;

    @Autowired
    private TaskNodeAuthComponent taskNodeAuthComponent;

    @Autowired
    private NodeCandidateService nodeCandidateService;

    @Autowired
    private FlowReNodeAuthRepository nodeAuthService;


    @Autowired
    protected ProcessEngineConfigurationImpl processEngineConfiguration;

    @Autowired
    private FlowNextNodeCandidateRepository flowNextNodeCandidateRepository;

    @Autowired
    private ResolveCandidateService resolveCandidateService;

    @Autowired
    private UserOrgService userOrgService;

    @Autowired
    private FlowCandidateServiceAdapter flowCandidateServiceAdapter;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private FlowTurnTaskService flowTurnTaskService;

    @Autowired
    private SyncProcessTaskProcessor syncProcessTaskProcessor;

    @Autowired
    private SyncTaskTracePostProcessor syncTaskTracePostProcessor;

    @Autowired
    private UserTaskManageService userTaskManageService;

    @Autowired
    private FlowExecutionQueryDAO flowExecutionQueryDAO;

    //后加签
    public static final String AFTER_ADDSIGN = "after";

    @Override
    public ResponseResult getTaskSkipList(String processInstanceId) {
        Map<String, Object> dataMap = new HashMap<>(4);
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(processInstance)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "流程不存在或已完成");
        }
        String taskIdStr = taskService.createTaskQuery().processInstanceId(processInstanceId).list().stream()
                .map(TaskInfo::getId).collect(Collectors.joining(","));
        TaskTraceQueryVo taskTraceQueryVo = new TaskTraceQueryVo();
        taskTraceQueryVo.setTaskIdStr(taskIdStr);
        taskTraceQueryVo.setProcessInstanceIdStr(processInstanceId);
        List<FlowTaskTraceVo> flowTaskTraceVoList = flowTaskTraceRepository.queryTaskTraces(taskTraceQueryVo);
        if (flowTaskTraceVoList.size() == 0) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "任务不存在或已完成");
        }

        Collection<FlowElement> flowElements = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()).getMainProcess().getFlowElements();
        List<Object> curNodeList = new ArrayList<>(flowTaskTraceVoList.size());
        List<String> curNodeIdList = new ArrayList<>(flowTaskTraceVoList.size());
        flowTaskTraceVoList.forEach(flowTaskTraceVo -> {
            Map<String, String> currentNode = new HashMap<>();
            currentNode.put("id", flowTaskTraceVo.getActivityId());
            currentNode.put("name", flowTaskTraceVo.getTaskName());
            currentNode.put("taskId", flowTaskTraceVo.getTaskId());
            curNodeIdList.add(flowTaskTraceVo.getActivityId());
            curNodeList.add(currentNode);
        });
        List<Object> elements = new ArrayList<>(8);
        flowElements.stream()
                .filter(this::judgeFlowElement)
                .filter(element -> !curNodeIdList.contains(element.getId()))
                .sorted(Comparator.comparing(flowElement -> {
                    if (flowElement instanceof StartEvent) {
                        return -1;
                    } else if (flowElement instanceof EndEvent) {
                        return 1;
                    } else {
                        return 0;
                    }
                })).forEach(flowElement -> {
            if (flowElement instanceof SubProcess) {
                ((SubProcess) flowElement).getFlowElements().stream()
                        .filter(subFlowElement -> subFlowElement instanceof UserTask)
                        .forEach(subFlowElement -> this.packageElement(elements, subFlowElement));
            } else {
                this.packageElement(elements, flowElement);
            }
        });
        dataMap.put("currentActivity", curNodeList);
        dataMap.put("newActivity", elements);
        dataMap.put("processInstanceId", processInstanceId);
        return ResponseResult.success(dataMap);
    }

    private boolean judgeFlowElement(FlowElement flowElement) {
        return flowElement instanceof StartEvent || flowElement instanceof EndEvent || flowElement instanceof UserTask || flowElement instanceof SubProcess;
    }

    private void packageElement(List<Object> elements, FlowElement flowElement) {
        Map<String, String> elementMap = new HashMap<>(4);
        elementMap.put("id", flowElement.getId());
        elementMap.put("name", flowElement.getName());
        elements.add(elementMap);
    }

    @Override
    @Transactional
    public ResponseResult skipTask(TaskSkipVo taskSkipVo) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(taskSkipVo.getProcessInstanceId()).singleResult();
        if (Objects.isNull(processInstance)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "流程不存在或已完成");
        }
        if (processInstance.isSuspended()) {
            return ResponseResult.fail(ErrorCode.PROCESS_SUSPEND_ERROR.errCode(), "流程已挂起");
        }

        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        FlowElement currentElement = bpmnModel.getFlowElement(taskSkipVo.getCurrentActivityId());
        FlowElement targetElement = bpmnModel.getFlowElement(taskSkipVo.getNewActivityId());
        if (Objects.isNull(currentElement) || Objects.isNull(targetElement)) {
            return ResponseResult.fail(ErrorCode.NODE_NOT_EXIST.errCode(), ErrorCode.NODE_NOT_EXIST.errMessage());
        }

        if (taskSkipVo.getFlowParamList() != null && taskSkipVo.getFlowParamList().size() > 0) {
            runtimeService.setVariables(processInstance.getId(), taskSkipVo.getFlowParamList());
        }

        Model model = repositoryService.createModelQuery().modelKey(bpmnModel.getMainProcess().getId()).list().stream()
                .filter(i -> processInstance.getDeploymentId().equals(i.getDeploymentId())).findAny().orElse(null);
        if (Objects.isNull(model)) {
            return ResponseResult.fail(ErrorCode.MODEL_NOT_EXIST.errCode(), ErrorCode.MODEL_NOT_EXIST.errMessage());
        }
        List<HashMap> list = new ArrayList<>();
        String editorSource = new String(repositoryService.getModelEditorSource(model.getId()), StandardCharsets.UTF_8);
        Objects.requireNonNull(JsonUtils.toObject(editorSource, ProcessModelVo.class)).getChildShapes().stream()
                .map(child -> (LinkedHashMap) child)
                .map(child -> (LinkedHashMap) child.get("properties"))
                .filter(child -> child.get("overrideid").equals(targetElement.getId()))
                .findAny().ifPresent(child -> {
            if (CollectionUtils.isEmpty((List<HashMap>) child.get("candidateUsers"))) {
                return;
            }
            List<HashMap> varList = ((List<HashMap>) child.get("candidateUsers")).stream()
                    .filter(i -> i.get("type").equals("VAR"))
                    .collect(Collectors.toList());
            if (varList.size() > 0) {
                Map<String, Object> variables = runtimeService.getVariables(processInstance.getProcessInstanceId());
                varList.forEach(v -> {
                    if (Objects.isNull(variables.get(v.get("code")))) {
                        list.add(v);
                    }
                });
            }
        });
        if (list.size() > 0) {
            return ResponseResult.fail(ErrorCode.NODE_ASSIGNEE_NOT_EXIST.errCode(), ErrorCode.NODE_ASSIGNEE_NOT_EXIST.errMessage(), "跳转节点的办理人变量未配置", list);
        }
        if (Objects.nonNull(taskSkipVo.getComment())) {
            taskService.addComment(taskSkipVo.getTaskId(), processInstance.getProcessInstanceId(), "moveComment", taskSkipVo.getComment());
        }
        Set<String> executionIdList = new HashSet<>();
        Set<String> mulExecutionIdList = new HashSet<>();
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskSkipVo.getProcessInstanceId()).list();
        FlowUtils.getInstance().changeActivityState(processInstance, taskSkipVo.getTaskId(), taskSkipVo.getCurrentActivityId(), taskSkipVo.getNewActivityId(), executionIdList, mulExecutionIdList);

        FlowTaskTraceVo flowTaskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(taskSkipVo.getTaskId());
        User current = userRepository.getCurrentUser();
        flowTaskTrace.setOperator(current.getUserName());
        flowTaskTrace.setOperatorCode(current.getUserId());
        if (Objects.nonNull(flowTaskTrace)) {
            if (StringUtils.isNotEmpty(flowTaskTrace.getParentId())) {
//                flowTaskTraceRepository.getTaskTraceByParentId(flowTaskTrace.getParentId()).forEach(flowTaskTraceVo -> this.updateTaskTrace(flowTaskTraceVo));
                mulExecutionIdList.add(flowTaskTrace.getParentId());
            }
            this.updateTaskTrace(flowTaskTrace);
        } else {
            this.insertTaskTrace(taskSkipVo.getProcessInstanceId());
        }

        if (CollectionUtils.isNotEmpty(executionIdList)) {
            taskList.stream().filter(task -> executionIdList.contains(task.getExecutionId())).map(TaskInfo::getId).forEach(taskId -> {
                FlowTaskTraceVo taskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(taskId);
                if (Objects.nonNull(taskTrace)) {
                    this.updateTaskTrace(taskTrace);
                }
            });
        }
        if (CollectionUtils.isNotEmpty(mulExecutionIdList)) {
            mulExecutionIdList.forEach(executionId -> {
                FlowMultiInstanceTaskTraceVo multiRootTaskTrace = flowMultiInstanceTaskTraceRepository.getByRootExecutionId(executionId);
                if (Objects.nonNull(multiRootTaskTrace)) {
                    multiRootTaskTrace.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
                    flowMultiInstanceTaskTraceRepository.updateMultiInstanceTaskTrace(multiRootTaskTrace);
                }
            });
        }
        taskService.deleteTask(taskSkipVo.getTaskId());
        return ResponseResult.success();
    }

    private void updateTaskTrace(FlowTaskTraceVo flowTaskTrace) {
        flowTaskTrace.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
        flowTaskTrace.setCompleteTime(new Date());
        flowTaskTraceRepository.updateTaskTraceById(flowTaskTrace);
        this.syncDataByScene(flowTaskTrace.getTaskId(), TaskLinkStatusEnum.DONE.getCode());
    }

    private void insertTaskTrace(String processInstanceId) {
        FlowTaskTraceVo taskTrace = new FlowTaskTraceVo();
        taskTrace.setProcessInstanceId(processInstanceId);
        taskTrace.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
        taskTrace.setStatus(ProcessInstanceStatusEnum.NORMAL.getCode());
        taskTrace.setFlag(0);
        taskTrace.setCreateTime(new Date());
        User current = userRepository.getCurrentUser();
        taskTrace.setOperator(current.getUserName());
        taskTrace.setOperatorCode(current.getUserId());
        FlowProcessInstanceTraceRepository processInstanceTraceService = SpringUtils.getBean(FlowProcessInstanceTraceRepository.class);
        FlowProcessInstanceTraceVo piTrace = processInstanceTraceService.getProcessInstanceTraceByProcessInstanceId(processInstanceId);
        if (Objects.nonNull(piTrace)) {
            taskTrace.setAppId(piTrace.getAppId());
            taskTrace.setBusiId(piTrace.getBusiId());
            taskTrace.setModelName(piTrace.getModelName());
            taskTrace.setSerialNum(piTrace.getSerialNum());
            taskTrace.setModelKey(piTrace.getModelKey());
            taskTrace.setTenantId(piTrace.getTenantId());
        }
        flowTaskTraceRepository.insertTaskTrace(taskTrace);
    }

    @Override
    public void backToStep(Task task, TaskHandleVo taskHandleVo) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        Activity activity = (Activity) repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()).getMainProcess().getFlowElement(task.getTaskDefinitionKey());
        List<SequenceFlow> sequenceFlows = activity.getIncomingFlows();
        for (SequenceFlow sequenceFlow : sequenceFlows) {
            FlowElement flowElement = sequenceFlow.getSourceFlowElement();
            if (flowElement instanceof ParallelGateway) {
                List<SequenceFlow> parallelGatewayOutgoingFlows = ((ParallelGateway) flowElement).getOutgoingFlows();
                for (SequenceFlow outgoingFlow : parallelGatewayOutgoingFlows) {
                    if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {

                    }
                }
                break;
            }
            if (flowElement instanceof InclusiveGateway) {
                List<SequenceFlow> inclusiveGatewayOutgoingFlows = ((InclusiveGateway) flowElement).getOutgoingFlows();
                for (SequenceFlow outgoingFlow : inclusiveGatewayOutgoingFlows) {
                    if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {

                    }
                }
                break;
            }
        }

    }

    @Override
    public ResponseResult getTaskBackList(String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "任务不存在或已处理");
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "任务不存在或已处理");
        }

        Map<String, Object> dataMap = new HashMap<>(4);

        //当前任务节点信息
        Map<String, String> curElement = new HashMap<>(2);
        curElement.put("id", task.getTaskDefinitionKey());
        curElement.put("name", task.getName());
        dataMap.put("currentActivity", curElement);

        //待回退的节点列表信息
        Process mainProcess = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
        List<FlowElement> flowElementBeforeCurrentElement = FlowUtils.getInstance().getFlowElementBeforeCurrentElement(mainProcess, task.getTaskDefinitionKey());
        List<Object> elements = new ArrayList<>();
        for (FlowElement flowElement : flowElementBeforeCurrentElement) {
            Map<String, String> elementMap = new HashMap<>(2);
            elementMap.put("id", flowElement.getId());
            elementMap.put("name", flowElement.getName());
            elements.add(elementMap);
        }

        dataMap.put("newActivity", elements);
        dataMap.put("taskId", taskId);

        return ResponseResult.success(dataMap);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean rollback(TaskRollbackVo taskRollbackVo) {
        if (StringUtils.isEmpty(taskRollbackVo.getTaskId())) {
            return false;
        }

        User user = userRepository.getCurrentUser();
        try {
            rollbackService.rollbackToPreNode(taskRollbackVo, user.getUserCode());
        } catch (Exception e) {
            logger.error("任务节点回退失败 s%", taskRollbackVo.getTaskId());
            return false;
        }
        return true;
    }

    private List<String> resolveTargetNodeCode(String currentNodeCode, String processDefinitionId) {
        List<FlowElement> targetFlowElements = FlowUtils.getInstance().getFirstFrontElement(currentNodeCode, processDefinitionId);
        return targetFlowElements.stream().map(BaseElement::getId).distinct().collect(Collectors.toList());
    }


    private void publishActivityJumpEvent(String comment, List<String> targetNodeCodes, Task currentTask, List<Task> currentTasks) {

        if (Objects.nonNull(targetNodeCodes)) {
            targetNodeCodes.stream().forEach(targetNodeCode -> {
                ActivityJumpEvent event = new ActivityJumpEvent();
                FlowElement flowElement = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getFlowElement(targetNodeCode);
                if (Objects.nonNull(flowElement)) {
                    event.setNewActivityName(flowElement.getName());
                }
                event.setCreatorName(userRepository.getCurrentUser().getUserName());
                event.setCurrentTasks(currentTasks);
                event.setNewActivityId(targetNodeCode);
                event.setProcessInstanceId(currentTask.getProcessInstanceId());
                event.setComment(comment);
                SpringUtils.publishEvent(event);
            });
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult turnTask(TurnTaskVo turnTaskVo) {
        User user = userRepository.getCurrentUser();
        if (Objects.equals(user.getUserCode(), turnTaskVo.getTurnToUserCode())) {
            return ResponseResult.fail(ErrorCode.CAN_NOT_ASSIGN_SELF.errCode(), ErrorCode.CAN_NOT_ASSIGN_SELF.errMessage());
        }
        return dealTurnTask(turnTaskVo, user);
    }

    @Override
    public ResponseResult dealTurnTask(TurnTaskVo turnTaskVo, User user) {
        CheckResult checkResult = checkAssignee(turnTaskVo.getTaskId(), user);
        if (!checkResult.isSuccess()) {
            return ResponseResult.fail(checkResult.getCode(), checkResult.getMsg());
        }

        Task task = taskService.createTaskQuery().taskId(turnTaskVo.getTaskId()).singleResult();

        if (StringUtils.isBlank(turnTaskVo.getComment())) {
            boolean needComment = isRequiredComment(task.getProcessInstanceId(), task.getTaskDefinitionKey());
            if (needComment) {
                return ResponseResult.fail(ErrorCode.COMMENT_NOT_EXIST.errCode(), ErrorCode.COMMENT_NOT_EXIST.errMessage());
            }
        }
        return flowTurnTaskService.turnTask(task, turnTaskVo);
    }


    @Override
    public ResponseResult appointNextNodeAssignee(NextNodeAssigneeTaskDTO nextNodeAssigneeTaskDTO) {
        User user = userRepository.getCurrentUser();

        Task currTask = queryTaskByCandidate(nextNodeAssigneeTaskDTO.getTaskId(), user);
        if (Objects.isNull(currTask)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(currTask.getProcessInstanceId()).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processInstance.getDeploymentId()).singleResult();

        List<SequenceFlow> outgoingFlows = getNextFlowNodeByProcesDefinitionId(processDefinition.getId(), currTask.getTaskDefinitionKey());

        if (Objects.isNull(outgoingFlows)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }
        if (outgoingFlows.size() > 1) {
            return ResponseResult.fail(ErrorCode.MULTI_NEXT_NODE.errCode(), ErrorCode.MULTI_NEXT_NODE.errMessage());
        }

        FlowElement nextNode = outgoingFlows.get(0).getTargetFlowElement();
        if (nextNode instanceof UserTask) {
            String activityId = nextNode.getId();
//            List<NextNodeTempParamVo> nextNodeTempParams = nextNodeAssigneeTaskVo.getNextNodeTempParams();
            FlowNextNodeAssignee flowNextNodeAssignee = new FlowNextNodeAssignee();
            flowNextNodeAssignee.setNodeCode(activityId);
            flowNextNodeAssignee.setProcessInstanceId(processInstance.getProcessInstanceId());
            flowNextNodeAssignee.setNextAssignee(nextNodeAssigneeTaskDTO.getNextNodeAssignee());
            flowNextNodeAssignee.save();

            if (StringUtils.isNotBlank(nextNodeAssigneeTaskDTO.getComment())) {
                this.addComment(currTask.getId(), user.getUserCode(), currTask.getProcessInstanceId(), CommentTypeEnum.SQ.name(), nextNodeAssigneeTaskDTO.getComment());
            }
            return ResponseResult.success();
        } else {
            return ResponseResult.fail(ErrorCode.NEXT_NODE_NOT_USER_TASK.errCode(), ErrorCode.NEXT_NODE_NOT_USER_TASK.errMessage());
        }
    }

    @Override
    public ResponseResult getNextNodeAssgineeParam(BaseTaskVo baseTaskVo) {

        TaskEntityImpl currTask = (TaskEntityImpl) taskService.createTaskQuery().taskId(baseTaskVo.getTaskId()).singleResult();
        if (Objects.isNull(currTask)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(currTask.getProcessInstanceId()).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processInstance.getDeploymentId()).singleResult();

        List<SequenceFlow> outgoingFlows = getNextFlowNodeByProcesDefinitionId(processDefinition.getId(), currTask.getTaskDefinitionKey());

        if (Objects.isNull(outgoingFlows)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }
        if (outgoingFlows.size() > 1) {
            return ResponseResult.fail(ErrorCode.MULTI_NEXT_NODE.errCode(), ErrorCode.MULTI_NEXT_NODE.errMessage());
        }

        FlowElement nextNode = outgoingFlows.get(0).getTargetFlowElement();

        if (nextNode instanceof UserTask) {
            String activityId = nextNode.getId();
            //如果有表达式
            FlowVarExpression flowVarExpression = getFlowVarExpression(processDefinition.getId(), activityId);
            if (Objects.nonNull(flowVarExpression)) {
                String expressionConent = flowVarExpression.getExpression();
                expressionConent = expressionConent.replace("${", "");
                expressionConent = expressionConent.replace("}", "");
                if (Objects.nonNull(expressionConent)) {
                    return ResponseResult.success(expressionConent);
                } else {
                    return ResponseResult.fail(ErrorCode.EXPRESS_SETTING_ERROR.errCode(), ErrorCode.EXPRESS_SETTING_ERROR.errMessage());
                }
            } else {
                return ResponseResult.fail(ErrorCode.ASSIGNEE_NOT_FROM_PARAM.errCode(), ErrorCode.ASSIGNEE_NOT_FROM_PARAM.errMessage());
            }
        } else {
            return ResponseResult.fail(ErrorCode.NEXT_NODE_NOT_USER_TASK.errCode(), ErrorCode.NEXT_NODE_NOT_USER_TASK.errMessage());
        }
    }

    @Override
    public List<SequenceFlow> getNextFlowNodeByProcessInstanceId(String processInstanceId, String currentActivityId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(processInstance)) {
            return null;
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processInstance.getDeploymentId()).singleResult();
        return getNextFlowNodeByProcesDefinitionId(processDefinition.getId(), currentActivityId);
    }

    @Override
    public List<SequenceFlow> getNextFlowNodeByProcesDefinitionId(String procesDefinitionId, String currentActivityId) {
        Collection<FlowElement> flowElements = repositoryService.getBpmnModel(procesDefinitionId).getMainProcess().getFlowElements();
        List<SequenceFlow> outgoingFlows = null;
        for (FlowElement flowElement : flowElements) {
            if (flowElement.getId().equals(currentActivityId)) {
                outgoingFlows = ((FlowNode) flowElement).getOutgoingFlows();
                break;
            }
        }
        return outgoingFlows;
    }


    public FlowVarExpression getFlowVarExpression(String processDefinitionId, String activityId) {
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);
        if (processDefinition == null) {
            return null;
        }

        // 获取表达式
        String deploymentId = processDefinition.getDeploymentId();
        FlowVarExpressionExample flowVarExpressionExample = new FlowVarExpressionExample();
        flowVarExpressionExample.createCriteria().andActivityIdEqualTo(activityId).andDeployIdEqualTo(deploymentId);
        List<FlowVarExpression> flowVarExpressions = flowVarExpressionDAO.selectByExample(flowVarExpressionExample);
        return (Objects.isNull(flowVarExpressions) || flowVarExpressions.size() == 0) ? null : flowVarExpressions.get(0);
    }

    @Override
    public ResponseResult claim(TaskClaimVo taskClaimVo) {
        User user = userRepository.getCurrentUser();
        logger.debug("当前用户信息为：{}", JSONObject.toJSONString(user));
        TaskQuery taskQuery = taskService.createTaskQuery().or().taskCandidateOrAssigned(user.getUserCode());
        if (StrUtil.isEmpty(user.getOrgCode())) {
            logger.warn("当前用户未指定组织或者用户组");
        } else {
            taskQuery.taskCandidateGroupIn(Arrays.asList(user.getOrgCode().split(",")));
        }
        taskQuery.endOr();

        Task task = taskQuery.taskId(taskClaimVo.getTaskId()).singleResult();
        if (Objects.isNull(task)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "任务不存在");
        }
        if (Objects.nonNull(task.getAssignee())) {
            return ResponseResult.fail(ErrorCode.TASK_CLAIM_ERROR.errCode(), "任务已签收");
        }
        try {

            if (StringUtils.isNotBlank(taskClaimVo.getComment())) {
                this.addComment(task.getId(), user.getUserCode(), task.getProcessInstanceId(), CommentTypeEnum.QS.getName(), taskClaimVo.getComment());
            }
            //1.签收
            taskService.claim(taskClaimVo.getTaskId(), user.getUserCode());
            //2.消息发送
            if (CollectionUtils.isNotEmpty(taskClaimVo.getReceiveMessagers())) {
                for (String str : taskClaimVo.getReceiveMessagers()) {
                    this.sendMessage(taskClaimVo.getTaskId(), taskClaimVo.getUserCode(), task.getProcessInstanceId(), str, MsgTypeEnum.TASK_CLAIM_NOTICE.getCode(),
                            taskClaimVo.getTitle(), taskClaimVo.getContent());
                }
            }
            //3.给操作记录赋值
            FlowTaskTrace flowTaskTrace = new FlowTaskTrace();
            flowTaskTrace.setOperator(user.getUserName());
            flowTaskTrace.setOperatorCode(user.getUserCode());
            flowTaskTrace.setUpdateTime(new Date());
            flowTaskTrace.setTaskId(taskClaimVo.getTaskId());
            flowTaskTrace.setProcessInstanceId(task.getProcessInstanceId());
            flowTaskTraceDAO.updateByTaskIdAndProcId(flowTaskTrace);
        } catch (FlowableTaskAlreadyClaimedException e) {
            return ResponseResult.fail(ErrorCode.TASK_CLAIM_ERROR.errCode(), "任务已签收");
        }
        return ResponseResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult complete(TaskHandleVo taskHandleVo) {
        TaskEntity task = null;
        User current = userRepository.getCurrentUser();
        task = (TaskEntity) taskService.createTaskQuery().taskCandidateOrAssigned(current.getUserCode()).taskId(taskHandleVo.getTaskId()).singleResult();
        if (Objects.isNull(task)) {
            logger.warn("任务：{} 不存在", taskHandleVo.getTaskId());
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        if (processInstance.isSuspended()) {
            logger.warn("流程已挂起");
            return ResponseResult.fail(ErrorCode.PROCESS_SUSPEND_ERROR.errCode(), ErrorCode.PROCESS_SUSPEND_ERROR.errMessage());
        }

        return completeTask(taskHandleVo, task, current, processInstance);
    }

    private ResponseResult<Object> completeTask(TaskHandleVo taskHandleVo, Task task, User current, ProcessInstance processInstance) {
        taskService.setVariablesLocal(taskHandleVo.getTaskId(), taskHandleVo.getVariables());
        //消息发送
        List<FlowNoticeTemplateVo> flowNoticeTemplateVos = flowNoticeTemplateRepository.getTemplateListByType(MsgTypeEnum.TASK_COMPLETED_NOTICE.getCode());
        if (CollectionUtils.isNotEmpty(flowNoticeTemplateVos)) {
            FlowNoticeTemplateVo flowNoticeTemplateVo = flowNoticeTemplateVos.get(0);
            FlowProcessInstanceTraceVo pt = processInstanceTraceRepository.getProcessInstanceTraceByProcessInstanceId(processInstance.getProcessInstanceId());
            if (Objects.nonNull(pt)) {
                this.sendMessage(taskHandleVo.getTaskId(), current.getUserCode(), processInstance.getProcessInstanceId(), pt.getStarterId(), MsgTypeEnum.TASK_COMPLETED_NOTICE.getCode(),
                        flowNoticeTemplateVo.getTitle(), flowNoticeTemplateVo.getContent());
            }
        }
        String formKey = task.getFormKey();

        //校验是否必填审批意见
        if (StringUtils.isBlank(taskHandleVo.getComment())) {
            boolean needComment = isRequiredComment(task.getProcessInstanceId(), task.getTaskDefinitionKey());
            if (needComment) {
                return ResponseResult.fail(ErrorCode.COMMENT_NOT_EXIST.errCode(), ErrorCode.COMMENT_NOT_EXIST.errMessage());
            }
        }

        //是否强制表态
        //如果强制表态，则必须包含key: approval
        if (checkIsRequired(task.getProcessInstanceId(), task.getTaskDefinitionKey(), MUST_EXPRESS)) {
            if (Objects.isNull(taskHandleVo.getVariables()) || !taskHandleVo.getVariables().containsKey("approval")) {
                return ResponseResult.fail(PARAM_NOT_EXIST.errCode(), "当前任务是强制表态，variables中必须包含参数：approval");
            }
        }


        //保存任务审批记录
        if (StringUtils.isNotBlank(taskHandleVo.getComment())) {
            this.addComment(task.getId(), current.getUserCode(), task.getProcessInstanceId(), CommentTypeEnum.SP.getName(), taskHandleVo.getComment());
        }

        taskService.complete(taskHandleVo.getTaskId(), taskHandleVo.getVariables());

        if (StringUtils.isNotEmpty(formKey) && MapUtil.isNotEmpty(taskHandleVo.getVariables())) {
            //保存表单数据
            formInstanceRepository.insertFormInstance(resolveFromInstance(task, taskHandleVo));
            //这里还要保存一份数据到草稿表,后续驳回的时候，直接从草稿表获取最后的填报数据
            formInstanceDraftRepository.addFormInstanceDraft(resolveFormInstanceDraft(task, taskHandleVo));
        }

        //处理加签父任务
        String parentTaskId = task.getParentTaskId();

        if (StringUtils.isNotBlank(parentTaskId)) {
            boolean completed = false;
            Task taskParent = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
            if (AFTER_ADDSIGN.equals(taskParent.getScopeType())) {
                String approval = "pass";
                if (Objects.nonNull(taskHandleVo.getVariables()) && Objects.nonNull(taskHandleVo.getVariables().get("approval"))) {
                    String.valueOf(taskHandleVo.getVariables().get("approval"));
                }
                //如果处理结果是不通过
                //则完成父任务，剩余的子任务也标记为完成
                if (!Objects.equals(approval, "pass")) {
                    List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskParent.getProcessInstanceId()).taskDefinitionKey(taskParent.getTaskDefinitionKey()).list();
                    //递归处理委派后再次加签的情况
                    dealSubTask(taskParent, taskList);

                    completed = true;

                    //处理父任务
                    taskService.complete(parentTaskId, taskHandleVo.getVariables());

                    //如果当前任务是委派后再加签，则加签的人处理意见为驳回，那么需要将委派的任务也给完成掉
                    String delegeTaskId = taskParent.getParentTaskId();
                    if (StringUtils.isNotBlank(delegeTaskId)) {
                        Task delegateTask = taskService.createTaskQuery().taskId(delegeTaskId).singleResult();
                        if (Objects.nonNull(delegateTask) && DelegationState.PENDING.equals(delegateTask.getDelegationState())) {
                            unPauseFlowTask(delegeTaskId);
                        }
                    }
                }
            }


            String tableName = managementService.getTableName(TaskEntity.class);
            String sql = "select count(1) from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
            long subTaskCount = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count();
            if (subTaskCount == 0 && !completed) {
                //处理前后加签的任务、委派任务
                unPauseFlowTask(parentTaskId);

                if (AFTER_ADDSIGN.equals(taskParent.getScopeType())) {
                    taskService.complete(parentTaskId, taskHandleVo.getVariables());
                }
            }
        }
        return ResponseResult.success();
    }


    public void dealSubTask(Task parentTask, List<Task> taskList) {
        if (Objects.nonNull(taskList) && taskList.size() > 0) {
            for (Task todoTask : taskList) {
                //处理所有子任务
                if (Objects.equals(todoTask.getParentTaskId(), parentTask.getId())) {
                    if (Objects.equals(DelegationState.PENDING, todoTask.getDelegationState())) {
                        //递归处理委派的情况
                        dealSubTask(todoTask, taskList);
                        taskService.resolveTask(todoTask.getId());
                    } else {
                        taskService.complete(todoTask.getId());
                    }
                    //更新flowTask状态为完成
                    setFlowTaskDone(todoTask.getId());
                }
            }
        }
    }

    private void unPauseFlowTask(String delegeTaskId) {
        FlowTaskTraceVo flowTaskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(delegeTaskId);
        if (Objects.nonNull(flowTaskTrace)) {
            if (ProcessInstanceStatusEnum.PAUSE.getCode().equals(flowTaskTrace.getStatus())) {
                flowTaskTrace.setStatus(ProcessInstanceStatusEnum.NORMAL.getCode());
                flowTaskTraceRepository.updateTaskTraceById(flowTaskTrace);
                // 同步给待办组件任务状态
                this.syncDataByScene(delegeTaskId, TaskLinkStatusEnum.TODO.getCode());
            }
        }
        //将委派任务完成掉
        taskService.resolveTask(delegeTaskId);
    }

    private void setFlowTaskDone(String delegeTaskId) {
        FlowTaskTraceVo flowTaskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(delegeTaskId);
        if (Objects.nonNull(flowTaskTrace)) {
            flowTaskTrace.setLinkStatus(TaskLinkStatusEnum.DONE.getCode());
            flowTaskTraceRepository.updateTaskTraceById(flowTaskTrace);
        }
    }

    /**
     * 外置表单去签审
     *
     * @param taskHandleVo 完成任务VO
     * @return
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult completeWithClaimAndExternalForm(TaskHandleVo taskHandleVo) {
        taskHandleVo = analyzeTaskHandleVO(taskHandleVo);
        FlowFormExternalInstanceDO flowFormExternalInstanceDO = new FlowFormExternalInstanceDO();
        String processInstanceId = taskTraceService.getTaskTraceByTaskId(taskHandleVo.getTaskId()).getProcessInstanceId();
        String formKey = flowFormRepository.resolveFormKeyFromTaskId(taskHandleVo.getTaskId());
        flowFormExternalInstanceDO.setProcessInstanceId(processInstanceId);
        flowFormExternalInstanceDO.setFormKey(formKey);
        //判断流程中是否已经存在以该formKey作为标识的表单
        FlowFormExternalInstanceDO formExternalInstanceDO = flowFormExternalInstanceDAO.selectExternalInstance(flowFormExternalInstanceDO);
        //如果在该流程中出现过
        if (Objects.nonNull(formExternalInstanceDO)) {
            return completeWithClaim(taskHandleVo);
        }
        //如果在流程中没有出现过，插入该流程
        flowFormExternalInstanceDO.setFormId(taskHandleVo.getFormId());
        flowFormExternalInstanceDAO.insertExternalInstance(flowFormExternalInstanceDO);
        return completeWithClaim(taskHandleVo);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult completeWithClaim(TaskHandleVo taskHandleVo) {
        User user = userRepository.getCurrentUser();
        CheckResult checkResult = checkAssignee(taskHandleVo.getTaskId(), user);
        if (!checkResult.isSuccess()) {
            return ResponseResult.fail(checkResult.getCode(), checkResult.getMsg());
        }
        Task task = taskService.createTaskQuery().taskId(taskHandleVo.getTaskId()).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        ResponseResult responseResult = completeTask(taskHandleVo, task, user, processInstance);
        return responseResult;
    }


    public Task queryTaskByCandidate(String taskId, User user) {
        FlowTaskTraceVo flowTaskTraceVo = getFlowTaskByTaskIdOrUserCode(taskId, user.getUserCode());
        if (Objects.isNull(flowTaskTraceVo)) {
            return null;
        }
        Task task = taskService.createTaskQuery().taskId(flowTaskTraceVo.getTaskId()).singleResult();
        return task;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult completeWithExternalForm(TaskHandleVo taskHandleVo) {
        //从第三方应用解析任务节点的变量
        taskHandleVo = analyzeTaskHandleVO(taskHandleVo);
        FlowFormExternalInstanceDO flowFormExternalInstanceDO = new FlowFormExternalInstanceDO();
        String processInstanceId = taskTraceService.getTaskTraceByTaskId(taskHandleVo.getTaskId()).getProcessInstanceId();
        String formKey = flowFormRepository.resolveFormKeyFromTaskId(taskHandleVo.getTaskId());
        flowFormExternalInstanceDO.setProcessInstanceId(processInstanceId);
        flowFormExternalInstanceDO.setFormKey(formKey);
        //判断流程中是否已经存在以该formKey作为标识的表单
        FlowFormExternalInstanceDO formExternalInstanceDO = flowFormExternalInstanceDAO.selectExternalInstance(flowFormExternalInstanceDO);
        //如果在该流程中出现过
        if (Objects.nonNull(formExternalInstanceDO)) {
            return complete(taskHandleVo);
        }
        //如果在流程中没有出现过，插入该流程
        flowFormExternalInstanceDO.setFormId(taskHandleVo.getFormId());
        flowFormExternalInstanceDAO.insertExternalInstance(flowFormExternalInstanceDO);
        return complete(taskHandleVo);
    }


    /**
     * 针对外置表单，对taskHandlevo进行处理
     *
     * @param taskHandleVo
     * @return
     */
    private TaskHandleVo analyzeTaskHandleVO(TaskHandleVo taskHandleVo) {
        //从第三方数据拿到用户填写的变量
        String formKey = flowFormRepository.resolveFormKeyFromTaskId(taskHandleVo.getTaskId());
        if (StringUtils.isNotBlank(formKey)) {
            FlowFormExternalInfoDomain flowFormExternalInfoDomain = flowFormRepository.findExternalFormInfo(formKey);
            if (Objects.nonNull(flowFormExternalInfoDomain) && StringUtils.isNotBlank(flowFormExternalInfoDomain.getGetDataUrl())) {
                //从当前任务获取流程变量
                Map<String, Object> map = flowFormRepository.getFormVariables(null, taskHandleVo.getTaskId());
                //对获取数据的url进行渲染
                String target = ParseRenderedVariable.parseRenderedVariable(flowFormExternalInfoDomain.getGetDataUrl(), map);
                //拼接formId
                target = target + (target.contains("?") ? "&" : "?") + "formId=" + taskHandleVo.getFormId();
                Map<String, Object> variables = restTemplate.getForObject(target, Map.class);
                // Map<String,Object> variables = restTemplate.getForObject(flowFormExternalInfoDO.getGetDataUrl()+"?formId="+taskHandleVo.getFormId(),Map.class);
                Map<String, Object> originVariables = taskHandleVo.getVariables();
                if (MapUtil.isNotEmpty(originVariables)) {
                    variables.putAll(originVariables);
                }
                taskHandleVo.setVariables(originVariables);
            }
        }

        return taskHandleVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveFormInstanceDraft(TaskHandleVo taskHandleVo) {
        //看看这个是否还在running
        Task task = taskService.createTaskQuery().taskId(taskHandleVo.getTaskId()).singleResult();
        if (Objects.isNull(task)) {
            logger.warn("任务{}不存在", taskHandleVo.getTaskId());
            return false;
        }
        //如果没表单，保存个毛线
        if (StrUtil.isEmpty(task.getFormKey()) || MapUtil.isEmpty(taskHandleVo.getVariables())) {
            logger.warn("该任务没有关联表单：{}", task.getId());
            return false;
        }
        //可以构建对象保存了。。。
        FormInstanceDraft formInstanceDraft = resolveFormInstanceDraft(task, taskHandleVo);
        return formInstanceDraftRepository.addFormInstanceDraft(formInstanceDraft);
    }

    @Override
    public ResponseResult<List<UserMeta>> getAssignee(BaseTaskVo baseTaskVo) {
        String taskId = baseTaskVo.getTaskId();
        List<UserMeta> assignList = getAssignee(taskId);
        return Objects.isNull(assignList) ? ResponseResult.fail(
                ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage()) :
                ResponseResult.success(assignList);
    }

    @Override
    public List<UserMeta> getAssignee(String taskId) {
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(taskEntity)) {
            return null;
        }

        FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
        flowTaskTraceExample.createCriteria()
                .andParentIdEqualTo(taskEntity.getParentTaskId())
                .andProcessInstanceIdEqualTo(taskEntity.getProcessInstanceId());
        List<FlowTaskTrace> flowTaskTraceList = flowTaskTraceDAO.selectByExample(flowTaskTraceExample);
        if (Objects.isNull(flowTaskTraceList)) {
            return null;
        }
        List<UserMeta> signeeList = new ArrayList<>();
        for (FlowTaskTrace flowTaskTrace : flowTaskTraceList) {
            UserMeta userMeta = new UserMeta();
            userMeta.setUserCode(flowTaskTrace.getOperatorCode());
            userMeta.setUserName(flowTaskTrace.getOperator());
            signeeList.add(userMeta);
        }
        return signeeList;
    }

    private FormInstanceDraft resolveFormInstanceDraft(Task task, TaskHandleVo taskHandleVo) {
        FormInstanceDraft result = new FormInstanceDraft();
        result.setProcessInstanceId(task.getProcessInstanceId());
        result.setTaskId(task.getId());
        result.setTaskName(task.getName());
        result.setTaskNodeCode(task.getTaskDefinitionKey());
        result.setFormKey(task.getFormKey());
        result.setLatestUpdate((byte) 1);
        result.setResource(JSONObject.toJSONString(taskHandleVo.getVariables()).getBytes(StandardCharsets.UTF_8));
        return result;
    }

    private FormInstanceDto resolveFromInstance(Task task, TaskHandleVo taskHandleVo) {
        FormInstanceDto formInstance = new FormInstanceDto();
        formInstance.setName(task.getFormKey() + ".form");
        formInstance.setTaskId(task.getId());
        formInstance.setProcessInstanceId(task.getProcessInstanceId());
        formInstance.setResource(JSONObject.parseObject(JSONObject.toJSONString(taskHandleVo.getVariables())));
        return formInstance;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult addSignTask(AddSignTaskVo addSignTaskVo) {
        User user = null;
        // 不为空,则根据加签人员编码查询获取用户信息
        if (StringUtils.isNotBlank(addSignTaskVo.getParticipantId())) {
            user = userService.getSingleUser(addSignTaskVo.getParticipantId());
        } else {
            user = userRepository.getCurrentUser();
        }

        // 检查用户信息是否为空
        if (Objects.isNull(user)) {
            return ResponseResult.fail(ErrorCode.USER_NOT_EXIST.errCode(), ErrorCode.USER_NOT_EXIST.errMessage());
        }
        // 检查被加签人列表
        List<String> signPersons = addSignTaskVo.getSignPersoneds();
        if (Objects.nonNull(signPersons) && !signPersons.isEmpty()) {
            for (String signPerson : signPersons) {
                //如果加签的人和当前人一样，则不允许加签
                if (Objects.equals(user.getUserCode(), signPerson)) {
                    return ResponseResult.fail(ErrorCode.CAN_NOT_ASSIGN_SELF.errCode(), ErrorCode.CAN_NOT_ASSIGN_SELF.errMessage());
                }
            }
        }

        // 根据任务id和用户编码获取是否节点操作权限
        NodeAuthVo nodeAuthVo = taskNodeAuthComponent.getNodeAuthByTaskIdAndUserCode(addSignTaskVo.getTaskId(), user.getUserCode());
        if (Objects.isNull(nodeAuthVo) || (Objects.nonNull(nodeAuthVo) && (Objects.isNull(nodeAuthVo.getAddSignature()) || !nodeAuthVo.getAddSignature()))) {
            return ResponseResult.fail(ErrorCode.NO_ADD_SIGN_AUTH.errCode(), ErrorCode.NO_ADD_SIGN_AUTH.errMessage());
        }

        CheckResult checkResult = checkAssignee(addSignTaskVo.getTaskId(), user);
        if (!checkResult.isSuccess()) {
            return ResponseResult.fail(checkResult.getCode(), checkResult.getMsg());
        }

        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery().taskId(addSignTaskVo.getTaskId()).singleResult();
        //如果节点配置了必须填写意见，则返回异常
        if (StringUtils.isBlank(addSignTaskVo.getComment())) {
            boolean needComment = isRequiredComment(taskEntity.getProcessInstanceId(), taskEntity.getTaskDefinitionKey());
            if (needComment) {
                return ResponseResult.fail(ErrorCode.COMMENT_NOT_EXIST.errCode(), ErrorCode.COMMENT_NOT_EXIST.errMessage());
            }
        }
        if (StringUtils.isNotBlank(addSignTaskVo.getComment())) {
            this.addComment(taskEntity.getId(), user.getUserCode(), taskEntity.getProcessInstanceId(), CommentTypeEnum.HJQ.getName(), addSignTaskVo.getComment());
        }

        //是否会签节点
        boolean isMultiTask = FlowUtils.getInstance().isMultiTaskActivity(taskEntity.getProcessInstanceId(), taskEntity.getTaskDefinitionKey());

        //会签节点加签
        if (isMultiTask) {

            FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
            flowTaskTraceExample.createCriteria().andTaskIdEqualTo(addSignTaskVo.getTaskId()).andProcessInstanceIdEqualTo(taskEntity.getProcessInstanceId());
            List<FlowTaskTrace> flowTaskTraces = flowTaskTraceDAO.selectByExample(flowTaskTraceExample);

            flowTaskTraceExample = new FlowTaskTraceExample();
            flowTaskTraceExample.createCriteria().andParentIdEqualTo(flowTaskTraces.get(0).getParentId()).andProcessInstanceIdEqualTo(taskEntity.getProcessInstanceId());
            //获取所有的兄弟任务
            List<FlowTaskTrace> broFlowTasks = flowTaskTraceDAO.selectByExample(flowTaskTraceExample);
            Map<String, String> multiTaskOperators = new HashMap<>();

            if (CollectionUtils.isNotEmpty(broFlowTasks)) {
                broFlowTasks.stream().forEach(flowTaskTrace -> {
                    multiTaskOperators.put(flowTaskTrace.getOperatorCode()
                            , StringUtils.isNotBlank(flowTaskTrace.getOperator()) ? flowTaskTrace.getOperator() : flowTaskTrace.getOperatorCode());
                });
            }

            for (String str : addSignTaskVo.getSignPersoneds()) {
                if (MapUtils.isNotEmpty(multiTaskOperators) && multiTaskOperators.containsKey(str)) {
                    return ResponseResult.fail(ErrorCode.ADD_SIGN_TASK_FAIL.errCode(), "用户[" + multiTaskOperators.get(str) + "]已在当前会签列表中");
                }
                // 检查是否需要设置用户变量信息
                userInfoHandleProcessor.checkSetUserVarInfo(user);

                runtimeService.addMultiInstanceExecution(taskEntity.getTaskDefinitionKey(),
                        taskEntity.getProcessInstanceId(), Collections.singletonMap("assignee", str));
            }


            //加签之后重新计算需处理人数
            recalculateHandler(taskEntity, flowTaskTraces.get(0).getParentId());

            if (CollectionUtils.isNotEmpty(addSignTaskVo.getReceiveMessagers())) {
                for (String str : addSignTaskVo.getReceiveMessagers()) {
                    this.sendMessage(addSignTaskVo.getTaskId(), addSignTaskVo.getUserCode(), taskEntity.getProcessInstanceId(), str, MsgTypeEnum.TASK_ADDSIGNTASK_NOTICE.getCode(),
                            addSignTaskVo.getTitle(), addSignTaskVo.getContent());
                }
            }
        } else if (Objects.nonNull(taskEntity.getParentTaskId())) {
            Task parentTask = taskService.createTaskQuery().taskId(taskEntity.getParentTaskId()).singleResult();
            //非普通节点加签，parentTask.scopeType 为空
            if (Objects.isNull(parentTask.getScopeType())) {
                //委派后加签，当作普通节点加签
                if (DelegationState.PENDING.equals(parentTask.getDelegationState())) {
                    firstAddSign(taskEntity, user, addSignTaskVo);
                }
            } else {
                //普通节点加签后再次加签user
                copySubTask(parentTask, addSignTaskVo, user);
            }
        } else {
            firstAddSign(taskEntity, user, addSignTaskVo);
        }
        return ResponseResult.success("加签成功");

    }

    /**
     * 普通节点第一次加签
     *
     * @param taskEntity
     * @param user
     * @param addSignTaskVo
     */
    private void firstAddSign(TaskEntityImpl taskEntity, User user, AddSignTaskVo addSignTaskVo) {
        //普通节点第一次加签
        taskEntity.setOwner(user.getUserCode());
        taskEntity.setAssignee(null);
        taskEntity.setCountEnabled(true);
        taskEntity.setScopeType(AFTER_ADDSIGN);
        // 检查是否需要设置用户变量信息
        userInfoHandleProcessor.checkSetUserVarInfo(user);
        //1.2 设置任务为空执行者
        taskService.saveTask(taskEntity);
        //            }
        //2.添加加签数据
        this.createSignSubTasks(addSignTaskVo, taskEntity, user);
        // 加签成功,则需要删除父节点任务
        List<String> taskIds = new ArrayList<>();
        taskIds.add(taskEntity.getId());
        this.syncTaskStatus(taskIds);
    }

    /**
     * 普通节点加签后再次加签
     *
     * @param task
     * @param addSignTaskVo
     */
    private void copySubTask(Task task, AddSignTaskVo addSignTaskVo, User user) {

        //拷贝任务
        List<String> signPersoneds = addSignTaskVo.getSignPersoneds();
        if (Objects.nonNull(signPersoneds) && signPersoneds.size() > 0) {
            signPersoneds.stream().forEach(singPerson -> {
                // 检查是否需要设置用户变量信息
                userInfoHandleProcessor.checkSetUserVarInfo(user);
                createSubTask(task, task.getId(), singPerson);
            });
        }
    }


    public void recalculateHandler(Task task, String parentExecutionId) {

        String processDefinitionId = task.getProcessDefinitionId();
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);

        String nodeCode = task.getTaskDefinitionKey();

        String completionCondition = null;
        List<CompletionCondition> completionConditionList = nodeCompletionConditionFactory.getCompletionConditons(processDefinition.getDeploymentId(), nodeCode);
        if (completionConditionList != null && completionConditionList.size() > 0) {
            completionCondition = completionConditionList.get(0).getValue();
        }

        int numOfHandler = 0;

        if (Objects.nonNull(completionCondition)) {

            String index;
            if (completionCondition.contains(">=")) {
                //解析出后面的数字
                index = "=";
            } else {
                index = ">";
            }
            String digital = completionCondition.substring(completionCondition.indexOf(index) + 1, completionCondition.length() - 1);
            int numOfInstances = (int) taskService.getVariable(task.getId(), MultiInstanceKeyEnum.NUMBER_OF_INSTANCES.getCode());
            if (completionCondition.contains("/")) {
                double rightValue = Double.parseDouble(digital) * numOfInstances;
                if (completionCondition.contains(">=")) {
                    numOfHandler = (int) Math.ceil(rightValue);
                } else {
                    numOfHandler = (int) Math.floor(rightValue + 1);
                }
            } else {
                if (completionCondition.contains(">=")) {
                    numOfHandler = Math.min(Integer.parseInt(digital), numOfInstances);
                } else {
                    numOfHandler = Math.min(Integer.parseInt(digital) + 1, numOfInstances);
                }
            }

            FlowMultiInstanceTaskTraceRepository multiInstanceTaskTraceService = SpringUtils.getBean(FlowMultiInstanceTaskTraceRepository.class);
            FlowMultiInstanceTaskTraceVo multiInstanceTaskTrace = multiInstanceTaskTraceService.getByRootExecutionId(parentExecutionId);
            if (Objects.nonNull(multiInstanceTaskTrace)) {
                multiInstanceTaskTrace.setNumOfHandler(numOfHandler);
                multiInstanceTaskTrace.setNumOfInstances(numOfInstances);
                multiInstanceTaskTraceService.updateMultiInstanceTaskTrace(multiInstanceTaskTrace);
            }

        }
    }

    /**
     * 创建加签子任务
     *
     * @param signVo     加签参数
     * @param taskEntity 父任务
     */
    private void createSignSubTasks(AddSignTaskVo signVo, TaskEntity taskEntity, User user) {
        if (CollectionUtils.isNotEmpty(signVo.getSignPersoneds())) {
            //            String parentTaskId = taskEntity.getId();
            //            if (StringUtils.isBlank(parentTaskId)) {
            //                parentTaskId = taskEntity.getId();
            //            }
            String finalParentTaskId = taskEntity.getId();
            //1.
            //            String taskId = taskEntity.getId();
            //            if (StringUtils.isBlank(taskEntity.getParentTaskId())) {
            //2.创建加签人的任务并执行完毕
            // 检查是否需要设置用户变量信息
            userInfoHandleProcessor.checkSetUserVarInfo(user);
            //创建当前任务的子任务
            Task task = this.createSubTask(taskEntity, finalParentTaskId, user.getUserCode());
            String taskId = task.getId();

            //记录加签的意见
            if (StringUtils.isNotBlank(signVo.getComment())) {
                this.addComment(taskId, user.getUserCode(), task.getProcessInstanceId(), CommentTypeEnum.HJQ.getName(), signVo.getComment());
            }


            //            }
            //2.创建被加签人的任务列表
            signVo.getSignPersoneds().forEach(userCode -> {
                if (StringUtils.isNotBlank(userCode)) {
                    // 检查是否需要设置用户变量信息
                    userInfoHandleProcessor.checkSetUserVarInfo(user);
                    this.createSubTask(taskEntity, finalParentTaskId, userCode);
                }
            });

            //主任务复制出来的子任务
            //如果主任务复制出来的子任务已经创建成功，则把主任务对应的flow_Task_trace删除
            Task taskInfo = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (null != taskInfo) {
                FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
                flowTaskTraceExample.createCriteria().andTaskIdEqualTo(signVo.getTaskId()).andProcessInstanceIdEqualTo(taskInfo.getProcessInstanceId());
                flowTaskTraceDAO.deleteByExample(flowTaskTraceExample);
            }
            //如果是候选人，需要删除运行时候选表种的数据。
            List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(finalParentTaskId);
            if (Objects.nonNull(identityLinkList) && !identityLinkList.isEmpty()) {
                for (IdentityLink identityLink : identityLinkList) {
                    if (StringUtils.isNotBlank(identityLink.getUserId())) {
                        taskService.deleteCandidateUser(finalParentTaskId, identityLink.getUserId());
                    } else if (StringUtils.isNotBlank(identityLink.getGroupId())) {
                        taskService.deleteCandidateUser(finalParentTaskId, identityLink.getGroupId());
                    }
                }
            }

            if (CollectionUtils.isNotEmpty(signVo.getReceiveMessagers())) {
                for (String str : signVo.getReceiveMessagers()) {
                    this.sendMessage(signVo.getTaskId(), user.getUserCode(), taskEntity.getProcessInstanceId(), str, MsgTypeEnum.TASK_ADDSIGNTASK_NOTICE.getCode(),
                            signVo.getTitle(), signVo.getContent());
                }
            }
        }
    }

    @Override
    public ResponseResult delayTask(DelayTaskVo delayTaskVo) {
        Long duration = delayTaskVo.getDay() * 24 * 3600 + delayTaskVo.getHour() * 3600 + delayTaskVo.getMinute() * 60;
        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery().taskId(delayTaskVo.getTaskId()).singleResult();
        FlowRuTimeoutSettingExample flowRuTimeoutSettingExample = new FlowRuTimeoutSettingExample();
        flowRuTimeoutSettingExample.createCriteria().andProcInstIdEqualTo(taskEntity.getProcessInstanceId());
        List<FlowRuTimeoutSetting> flowRuTimeoutSettings = flowRuTimeoutSettingDAO.selectByExample(flowRuTimeoutSettingExample);
        for (FlowRuTimeoutSetting flowRuTimeoutSetting : flowRuTimeoutSettings) {
            if (flowRuTimeoutSetting.getType().equals(MsgTypeEnum.PROCESS_TIMEOUT_NOTICE.getCode()) ||
                    flowRuTimeoutSetting.getType().equals(MsgTypeEnum.TASK_TIMEOUT_NOTICE.getCode())) {
                if (Objects.nonNull(cacheManager)) {
                    cacheManager.set(flowRuTimeoutSetting.getId() + "::" + taskEntity.getProcessInstanceId() + "::" + flowRuTimeoutSetting.getType(),
                            JSON.toJSONString(flowRuTimeoutSetting), duration, TimeUnit.SECONDS);
                }
            }
        }
        //延期消息发送
        if (CollectionUtils.isNotEmpty(delayTaskVo.getReceiveMessagers())) {
            for (String str : delayTaskVo.getReceiveMessagers()) {
                this.sendMessage(delayTaskVo.getTaskId(), delayTaskVo.getUserCode(), taskEntity.getProcessInstanceId(), str, MsgTypeEnum.TASK_DEPLAY_NOTICE.getCode(),
                        delayTaskVo.getTitle(), delayTaskVo.getContent());
            }
        }
        return ResponseResult.success();
    }


    @Override
    public ResponseResult getTaskTimeout(String taskId) {
        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery().taskId(taskId).singleResult();
        FlowRuTimeoutSettingExample flowRuTimeoutSettingExample = new FlowRuTimeoutSettingExample();
        flowRuTimeoutSettingExample.createCriteria().andProcInstIdEqualTo(taskEntity.getProcessInstanceId());
        List<FlowRuTimeoutSetting> flowRuTimeoutSettings = flowRuTimeoutSettingDAO.selectByExample(flowRuTimeoutSettingExample);
        Map<String, Object> map = new HashMap<>();
        Boolean flag = true;
        for (FlowRuTimeoutSetting flowRuTimeoutSetting : flowRuTimeoutSettings) {
            Calendar c = Calendar.getInstance();
            if (flowRuTimeoutSetting.getType().equals(NoticeTypeEnum.PROCESS_TIMEOUT_NOTICE.getCode())) {
                c.setTime(flowRuTimeoutSetting.getCreateTime());
                c.add(Calendar.SECOND, +flowRuTimeoutSetting.getDuration().intValue());
                map.put("process_timeout", c.getTime());
            }
            if (flowRuTimeoutSetting.getType().equals(NoticeTypeEnum.TASK_TIMEOUT_NOTICE.getCode())) {
                c.setTime(flowRuTimeoutSetting.getCreateTime());
                c.add(Calendar.SECOND, +flowRuTimeoutSetting.getDuration().intValue());
                map.put("task_timeout", c.getTime());
                flag = false;
            }
        }
        if (flag) {
            return ResponseResult.fail(1836554, "该任务未配置超时，不能延期操作");
        }
        return ResponseResult.success(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult delegateTask(TaskDelegateVo taskDelegateVo) {
        User user = null;
        // 不为空,则根据委派人员编码查询获取用户信息
        if (StringUtils.isNotBlank(taskDelegateVo.getParticipantId())) {
            user = userService.getSingleUser(taskDelegateVo.getParticipantId());
            // 检查是否需要设置用户变量信息
            userInfoHandleProcessor.checkSetUserVarInfo(user);
        } else {
            user = userRepository.getCurrentUser();
        }

        //如果处理任何要委派的人一致，则不允许委派
        // 检查用户是否存在
        if (Objects.isNull(user)) {
            return ResponseResult.fail(ErrorCode.USER_NOT_EXIST.errCode(), ErrorCode.USER_NOT_EXIST.errMessage());
        }

        if (Objects.equals(user.getUserCode(), taskDelegateVo.getDelegateUserCode())) {
            return ResponseResult.fail(ErrorCode.CAN_NOT_ASSIGN_SELF.errCode(), ErrorCode.CAN_NOT_ASSIGN_SELF.errMessage());
        }

        // 根据任务id和用户编码获取是否节点操作权限
        NodeAuthVo nodeAuthVo = taskNodeAuthComponent.getNodeAuthByTaskIdAndUserCode(taskDelegateVo.getTaskId(), user.getUserCode());
        if (Objects.isNull(nodeAuthVo) || (Objects.nonNull(nodeAuthVo) && (Objects.isNull(nodeAuthVo.getDelegate()) || !nodeAuthVo.getDelegate()))) {
            return ResponseResult.fail(ErrorCode.NO_DELEGATE_AUTH.errCode(), ErrorCode.NO_DELEGATE_AUTH.errMessage());
        }

        // 根据任务id和用户编码检查任务并更新任务审批trace信息
        CheckResult checkResult = this.checkAssigneeByTaskIdAndUser(taskDelegateVo.getTaskId(), user);
        if (!checkResult.isSuccess()) {
            return ResponseResult.fail(checkResult.getCode(), checkResult.getMsg());
        }

        // 获取单个任务实例
        Task task = flowBaseDataHandleProcessor.resolveTaskSingle(taskDelegateVo.getTaskId());
        if (Objects.isNull(task)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }

        // 类型转换
        TaskEntity taskEntity = (TaskEntity) task;
        // 校验是否是会签节点,如果是会签节点,则不允许委派操作
        Boolean isMultiTask = FlowUtils.getInstance().isMultiTaskActivity(taskEntity.getProcessInstanceId(), taskEntity.getTaskDefinitionKey());
        if (isMultiTask.booleanValue()) {
            return ResponseResult.fail(ErrorCode.NO_DELEGATE_AUTH_MULTI_TASK.errCode(), ErrorCode.NO_DELEGATE_AUTH_MULTI_TASK.errMessage());
        }

        // 将当前的任务设置为暂停状态
        FlowTaskTraceVo flowTaskTraceVo = flowTaskTraceRepository.getTaskTraceByTaskId(taskDelegateVo.getTaskId());
        if (Objects.nonNull(flowTaskTraceVo)) {
            flowTaskTraceVo.setUpdateTime(new Date());
            flowTaskTraceVo.setStatus(ProcessInstanceStatusEnum.PAUSE.getCode());
            flowTaskTraceVo.setOperator(user.getUserName());
            flowTaskTraceRepository.updateTaskTraceById(flowTaskTraceVo);
        }


        //处理意见框
        //如果节点配置了必须填写意见，则返回异常
        if (StringUtils.isBlank(taskDelegateVo.getComment())) {
            boolean needComment = isRequiredComment(task.getProcessInstanceId(), task.getTaskDefinitionKey());
            if (needComment) {
                return ResponseResult.fail(ErrorCode.COMMENT_NOT_EXIST.errCode(), ErrorCode.COMMENT_NOT_EXIST.errMessage());
            }
        }
        if (Objects.nonNull(taskDelegateVo.getComment())) {
            taskService.addComment(task.getId(), task.getProcessInstanceId(), CommentTypeEnum.WP.getName(), taskDelegateVo.getComment());
        }

        //设置当前任务的所有者
        taskService.setOwner(taskDelegateVo.getTaskId(), user.getUserCode());

        //将任务委派到某个人
        String delegateUserCode = taskDelegateVo.getDelegateUserCode();
        taskService.delegateTask(taskDelegateVo.getTaskId(), delegateUserCode);

        //创建子任务单
        createSubTask(task, task.getId(), delegateUserCode);

        // 委派成功之后,将委派任务暂停
        this.syncDataByScene(taskDelegateVo.getTaskId(), ProcessInstanceStatusEnum.PAUSE.getCode());

        //清除线程变量中的任务和实例
        return ResponseResult.success();
    }

    public CheckResult checkAssignee(String taskId, User user) {
        Task task = queryTaskByCandidate(taskId, user);
        if (Objects.isNull(task)) {
            return CheckResult.fail(ErrorCode.NOT_TASK_CANDIDATE_OR_TASK_NOT_EXIST.errCode(), ErrorCode.NOT_TASK_CANDIDATE_OR_TASK_NOT_EXIST.errMessage());
        }

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        if (processInstance.isSuspended()) {
            logger.warn("流程已挂起");
            return CheckResult.fail(ErrorCode.PROCESS_SUSPEND_ERROR.errCode(), ErrorCode.PROCESS_SUSPEND_ERROR.errMessage());
        }

        // 如果未设置审批人，则优先设置审批人
        // 相当于把签收的动作合并在处理中了
        if (StringUtils.isBlank(task.getAssignee())) {

            //先签收
            taskService.claim(task.getId(), user.getUserCode());

            //2.给操作记录赋值
            FlowTaskTrace flowTaskTrace = new FlowTaskTrace();
            flowTaskTrace.setOperator(user.getUserName());
            flowTaskTrace.setOperatorCode(user.getUserCode());
            flowTaskTrace.setUpdateTime(new Date());
            flowTaskTrace.setTaskId(taskId);
            flowTaskTrace.setProcessInstanceId(task.getProcessInstanceId());
            flowTaskTraceDAO.updateByTaskIdAndProcId(flowTaskTrace);
        }
        return CheckResult.success();
    }

    private String resolveParentId(TaskEntity taskEntity) {
        ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager().findById(taskEntity.getExecutionId());
        if (Objects.nonNull(execution)) {
            ExecutionEntity parent = execution.getParent();
            if (Objects.nonNull(parent) && parent.isMultiInstanceRoot()) {
                return parent.getId();
            }
        }
        return null;
    }


    private void resolveProcessInstanceRel(FlowTaskTrace taskTrace, String processInstanceId) {
        FlowProcessInstanceTraceRepository processInstanceTraceService = SpringUtils.getBean(FlowProcessInstanceTraceRepository.class);
        FlowProcessInstanceTraceVo piTrace = processInstanceTraceService.getProcessInstanceTraceByProcessInstanceId(processInstanceId);
        if (Objects.nonNull(piTrace)) {
            taskTrace.setAppId(piTrace.getAppId());
            taskTrace.setBusiId(piTrace.getBusiId());
            taskTrace.setModelName(piTrace.getModelName());
            taskTrace.setSerialNum(piTrace.getSerialNum());
            taskTrace.setModelKey(piTrace.getModelKey());
            taskTrace.setTenantId(piTrace.getTenantId());
        }
    }


    @Override
    public ResponseResult deleteSignTask(DeleteSignTaskVo deleteSignTaskVo) {
        User user = null;
        // 不为空,则根据减签人员编码查询获取用户信息
        if (StringUtils.isNotBlank(deleteSignTaskVo.getParticipantId())) {
            user = userService.getSingleUser(deleteSignTaskVo.getParticipantId());
        } else {
            user = userRepository.getCurrentUser();
        }

        // 检查用户信息是否为空
        if (Objects.isNull(user)) {
            return ResponseResult.fail(ErrorCode.USER_NOT_EXIST.errCode(), ErrorCode.USER_NOT_EXIST.errMessage());
        }
        // 检查被减签人列表
        List<String> signPersons = deleteSignTaskVo.getDeletedPersons();
        if (Objects.nonNull(signPersons) && !signPersons.isEmpty()) {
            for (String signPerson : signPersons) {
                //如果减签的人和当前人一样，则不允许减签
                if (Objects.equals(user.getUserCode(), signPerson)) {
                    return ResponseResult.fail(ErrorCode.CAN_NOT_DELETE_SELF.errCode(), ErrorCode.CAN_NOT_DELETE_SELF.errMessage());
                }
            }
        }

        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery().taskId(deleteSignTaskVo.getTaskId()).singleResult();
        //如果节点配置了必须填写意见，则返回异常
        if (StringUtils.isBlank(deleteSignTaskVo.getComment())) {
            boolean needComment = isRequiredComment(taskEntity.getProcessInstanceId(), taskEntity.getTaskDefinitionKey());
            if (needComment) {
                return ResponseResult.fail(ErrorCode.COMMENT_NOT_EXIST.errCode(), ErrorCode.COMMENT_NOT_EXIST.errMessage());
            }
        }
        if (StringUtils.isNotBlank(deleteSignTaskVo.getComment())) {
            this.addComment(taskEntity.getId(), user.getUserCode(), taskEntity.getProcessInstanceId(), CommentTypeEnum.JQ.getName(), deleteSignTaskVo.getComment());
        }

        //是否会签节点
        boolean isMultiTask = FlowUtils.getInstance().isMultiTaskActivity(taskEntity.getProcessInstanceId(), taskEntity.getTaskDefinitionKey());

        //会签节点减签
        if (isMultiTask) {

            FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
            flowTaskTraceExample.createCriteria().andTaskIdEqualTo(deleteSignTaskVo.getTaskId()).andProcessInstanceIdEqualTo(taskEntity.getProcessInstanceId());
            List<FlowTaskTrace> flowTaskTraces = flowTaskTraceDAO.selectByExample(flowTaskTraceExample);

            flowTaskTraceExample = new FlowTaskTraceExample();
            flowTaskTraceExample.createCriteria().andParentIdEqualTo(flowTaskTraces.get(0).getParentId()).andProcessInstanceIdEqualTo(taskEntity.getProcessInstanceId());
            //获取所有的兄弟任务
            List<FlowTaskTrace> broFlowTasks = flowTaskTraceDAO.selectByExample(flowTaskTraceExample);

            if (CollectionUtils.isNotEmpty(broFlowTasks)) {
                for (String str : signPersons) {
                    broFlowTasks.stream().forEach(flowTaskTrace -> {
                        if (flowTaskTrace.getOperatorCode().equals(str)) {
                            TaskEntityImpl task = (TaskEntityImpl) taskService.createTaskQuery().taskId(flowTaskTrace.getTaskId()).singleResult();
                            Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
                            runtimeService.deleteMultiInstanceExecution(execution.getId(), Boolean.FALSE);
                            flowTaskTraceRepository.deleteByPrimaryKey(flowTaskTrace.getId());
                        }
                    });
                }
            }

            //减签之后重新计算需处理人数
            recalculateHandler(taskEntity, flowTaskTraces.get(0).getParentId());

            if (CollectionUtils.isNotEmpty(deleteSignTaskVo.getReceiveMessagers())) {
                for (String str : deleteSignTaskVo.getReceiveMessagers()) {
                    this.sendMessage(deleteSignTaskVo.getTaskId(), deleteSignTaskVo.getUserCode(), taskEntity.getProcessInstanceId(), str, MsgTypeEnum.TASK_DELSIGNTASK_NOTICE.getCode(),
                            deleteSignTaskVo.getTitle(), deleteSignTaskVo.getContent());
                }
            }
        } else if (Objects.nonNull(taskEntity.getParentTaskId())) {
            Task parentTask = taskService.createTaskQuery().taskId(taskEntity.getParentTaskId()).singleResult();
            //非普通节点加签，parentTask.scopeType 为空
            if (Objects.isNull(parentTask.getScopeType())) {
                //委派后加签，当作普通节点加签
//                if (DelegationState.PENDING.equals(parentTask.getDelegationState())) {
//                    firstAddSign(taskEntity, user, addSignTaskVo);
//                }
            } else {
                //普通节点加签后再减签
                deleteSubTask(taskEntity, deleteSignTaskVo);
            }
        } else {
            deleteSubTask(taskEntity, deleteSignTaskVo);
        }
        return ResponseResult.success("减签成功");


//        Task task = null;
//        task = taskService.createTaskQuery().taskCandidateOrAssigned(user.getUserCode()).taskId(deleteSignTaskVo.getTaskId()).singleResult();
//        if (Objects.isNull(task)) {
//            logger.warn("任务：{} 不存在", deleteSignTaskVo.getTaskId());
//            throw new BusiException(ErrorCode.TASK_NOT_EXIST);
//        }
//
//        Execution execution = runtimeService.createExecutionQuery().executionId(deleteSignTaskVo.getExecutionId()).singleResult();
//
//        if (Objects.isNull(execution)) {
//            logger.warn("任务：{} 不存在", deleteSignTaskVo.getTaskId());
//            throw new BusiException(ErrorCode.TASK_NOT_EXIST);
//        }
//        runtimeService.deleteMultiInstanceExecution(execution.getId(), Boolean.FALSE);
//
//        if (CollectionUtils.isNotEmpty(deleteSignTaskVo.getReceiveMessagers())) {
//            for (String str : deleteSignTaskVo.getReceiveMessagers()) {
//                this.sendMessage(deleteSignTaskVo.getTaskId(), deleteSignTaskVo.getUserCode(), deleteSignTaskVo.getProcessInstanceId(), str, MsgTypeEnum.TASK_DELSIGNTASK_NOTICE.getCode(),
//                        deleteSignTaskVo.getTitle(), deleteSignTaskVo.getContent());
//            }
//        }
//
//        return ResponseResult.success();
    }

    /**
     * 普通节点加签后再次减签
     *
     * @param task
     * @param deleteSignTaskVo
     */
    private void deleteSubTask(Task task, DeleteSignTaskVo deleteSignTaskVo) {
        Task parentTask = taskService.createTaskQuery().taskId(task.getParentTaskId()).singleResult();
        //拷贝任务
        List<String> signPersons = deleteSignTaskVo.getDeletedPersons();
        if (Objects.nonNull(signPersons) && signPersons.size() > 0) {
            List<Task> subTasks = taskService.getSubTasks(parentTask.getId());
            signPersons.stream().forEach(singPerson -> {
                subTasks.stream().forEach(subtask -> {
                    if (singPerson.equals(subtask.getAssignee())) {
                        taskService.deleteTask(subtask.getId(), singPerson);
                        FlowTaskTraceVo flowTaskTrace = flowTaskTraceRepository.taskByTaskId(subtask.getId());
                        flowTaskTraceRepository.deleteByPrimaryKey(flowTaskTrace.getId());
                    }
                });
            });
        }
    }

    /**
     * 创建子任务
     *
     * @param ptask    创建子任务
     * @param assignee 子任务的执行人
     * @return
     */
    protected TaskEntity createSubTask(Task ptask, String ptaskId, String assignee) {
        TaskEntity task = null;
        if (ptask != null) {
            //1.生成子任务
            task = (TaskEntity) taskService.newTask(UUIDGenerator.generate());
            task.setCategory(ptask.getCategory());
            task.setDescription(ptask.getDescription());
            task.setTenantId(ptask.getTenantId());
            task.setAssignee(assignee);
            task.setName(ptask.getName());
            task.setParentTaskId(ptaskId);
            task.setProcessDefinitionId(ptask.getProcessDefinitionId());
            task.setProcessInstanceId(ptask.getProcessInstanceId());
            task.setTaskDefinitionKey(ptask.getTaskDefinitionKey());
            task.setTaskDefinitionId(ptask.getTaskDefinitionId());
            task.setPriority(ptask.getPriority());
            task.setCreateTime(new Date());
            task.setFormKey(ptask.getFormKey());
            //task.setVariablesLocal(managementService.executeCommand(new GetTaskVariablesCmd(ptaskId, null, false)));
            taskService.saveTask(task);
        }
        return task;
    }

    @Override
    public TaskDTO getUserCurrentTask(String processInstanceId) {
        User user = userRepository.getCurrentUser();
        TaskQuery taskQuery = taskService.createTaskQuery().or().taskCandidateOrAssigned(user.getUserCode());
        if (StrUtil.isEmpty(user.getOrgCode())) {
            logger.warn("当前用户未指定组织或者用户组");
        } else {
            taskQuery.taskCandidateGroupIn(Arrays.asList(user.getOrgCode().split(",")));
        }
        taskQuery.endOr();
        List<Task> taskList = taskQuery.processInstanceId(processInstanceId).list();

        if (Objects.nonNull(taskList) && taskList.size() > 0) {
            for (Task task : taskList) {
                //改变了flowable原生的委派，所以这边需要做二次判断
                //非委派状态的单子才是自己的
                if (!Objects.equals(DelegationState.PENDING, task.getDelegationState())) {
                    TaskDTO taskDTO = new TaskDTO();
                    taskDTO.setTaskId(task.getId());
                    return taskDTO;
                }
            }
        }
        return null;
    }

    @Override
    public List<FlowSpecifyTheNodeHandlerTaskQueryInfo> getSpecifyTheNodeHandlerTask(String taskId) {
        // 0、定义返回结果集对象
        Map<String, String> controlNodeMap = new HashMap<>();
        List<FlowSpecifyTheNodeHandlerTaskQueryInfo> returnDataList = new ArrayList<FlowSpecifyTheNodeHandlerTaskQueryInfo>();
        List<FlowSpecifyTheNodeHandlerTaskQueryInfo> specifyTheNodeHandlerTaskQueryInfoList = new ArrayList<FlowSpecifyTheNodeHandlerTaskQueryInfo>();
        // 1、根据taskId查询任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            return specifyTheNodeHandlerTaskQueryInfoList;
        }
        // 2、获取当前实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        if (Objects.isNull(processInstance)) {
            return specifyTheNodeHandlerTaskQueryInfoList;
        }
        // 2.1、获取ProcessDefinition实例
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
        // 3、获取活动
        Activity activity = (Activity) repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()).getFlowElement(task.getTaskDefinitionKey());
        // 3.1、获取当前节点所需处理的候选人信息
        List<ModelTaskCandidateSettings> candidateEntityList = flowTaskCandidateSettingsRepository.listModelTaskCandidateSettings(processInstance.getDeploymentId(), activity.getId());
        if (candidateEntityList != null && candidateEntityList.size() > 0) {
            if ("1".equalsIgnoreCase(candidateEntityList.get(0).getNextNodeHandler())) {
                String controlNode = candidateEntityList.get(0).getControlNode();
                if (StringUtils.isNotEmpty(controlNode)) {
                    String[] strArray = controlNode.substring(1, controlNode.length() - 1).split(",");
                    for (int i = 0; i < strArray.length; i++) {
                        controlNodeMap.put(strArray[i].replaceAll("\"", ""), strArray[i].replaceAll("\"", ""));
                    }
                }
            }
        }
        // 4、循环flow队列
        List<SequenceFlow> sequenceFlows = activity.getOutgoingFlows();
        for (SequenceFlow sequenceFlow : sequenceFlows) {
            FlowElement flowElement = sequenceFlow.getTargetFlowElement();
            processSpecifyNodeUserTaskCandidateData(specifyTheNodeHandlerTaskQueryInfoList, processDefinition, sequenceFlow, flowElement, task);
        }

        if (controlNodeMap != null && controlNodeMap.size() > 0) {
            for (FlowSpecifyTheNodeHandlerTaskQueryInfo vo : specifyTheNodeHandlerTaskQueryInfoList) {
                if (StringUtils.isNotEmpty(controlNodeMap.get(vo.getNodeCode()))) {
                    returnDataList.add(vo);
                }
            }
        }

        if (returnDataList != null && returnDataList.size() > 0 && controlNodeMap != null && controlNodeMap.size() > 0) {
            return returnDataList;
        } else {
            return specifyTheNodeHandlerTaskQueryInfoList;
        }
    }

    // 处理当前节点用户任务下一节点的所有用户任务候选人列表数据
    private void processSpecifyNodeUserTaskCandidateData(List<FlowSpecifyTheNodeHandlerTaskQueryInfo> specifyTheNodeHandlerTaskQueryInfoList, ProcessDefinition processDefinition, SequenceFlow sequenceFlow, FlowElement flowElement, Task task) {
        // 定义变量时网关类型的流程元素
        boolean isFlowGateway = false;
        // 4.1、当前流程元素为并行网关
        if (flowElement instanceof ParallelGateway) {
            isFlowGateway = true;
            List<SequenceFlow> parallelGatewayOutgoingFlows = ((ParallelGateway) flowElement).getOutgoingFlows();
            for (SequenceFlow outgoingFlow : parallelGatewayOutgoingFlows) {
                // 已处理过的节点不再进行处理（避免死循环）
                if (isProcessedData(specifyTheNodeHandlerTaskQueryInfoList, outgoingFlow.getTargetFlowElement())) {
                    return;
                }
                if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {
                    // 4.1.1、转换目标流程元素为用户任务对象
                    processFlowTaskCandidateSettingsData(specifyTheNodeHandlerTaskQueryInfoList, outgoingFlow, processDefinition, task);
                }
            }
        }
        // 4.2、当前流程元素为包含网关
        if (flowElement instanceof InclusiveGateway) {
            isFlowGateway = true;
            List<SequenceFlow> inclusiveGatewayOutgoingFlows = ((InclusiveGateway) flowElement).getOutgoingFlows();
            for (SequenceFlow outgoingFlow : inclusiveGatewayOutgoingFlows) {
                // 已处理过的节点不再进行处理（避免死循环）
                if (isProcessedData(specifyTheNodeHandlerTaskQueryInfoList, outgoingFlow.getTargetFlowElement())) {
                    return;
                }
                if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {
                    // 4.2.1、转换目标流程元素为用户任务对象
                    processFlowTaskCandidateSettingsData(specifyTheNodeHandlerTaskQueryInfoList, outgoingFlow, processDefinition, task);
                }
            }
        }
        // 4.3、当前流程元素为排他网关
        if (flowElement instanceof ExclusiveGateway) {
            isFlowGateway = true;
            List<SequenceFlow> exclusiveGatewayOutgoingFlows = ((ExclusiveGateway) flowElement).getOutgoingFlows();
            for (SequenceFlow outgoingFlow : exclusiveGatewayOutgoingFlows) {
                // 已处理过的节点不再进行处理（避免死循环）
                if (isProcessedData(specifyTheNodeHandlerTaskQueryInfoList, outgoingFlow.getTargetFlowElement())) {
                    return;
                }
                if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {
                    // 4.3.1、转换目标流程元素为用户任务对象
                    processFlowTaskCandidateSettingsData(specifyTheNodeHandlerTaskQueryInfoList, outgoingFlow, processDefinition, task);
                }
            }
        }
        // 当前节点为子流程类型
        if (Objects.nonNull(flowElement) && flowElement instanceof SubProcess) {
            UserTask tempUserTask = null;
            Collection<FlowElement> subProcessEls = ((SubProcess) flowElement).getFlowElements();
            for (FlowElement fe : subProcessEls) {
                if (fe instanceof UserTask) {
                    List<SequenceFlow> outgoingFlows = ((UserTask) fe).getOutgoingFlows();
                    for (SequenceFlow outgoing : outgoingFlows) {
                        // 已处理过的节点不再进行处理（避免死循环）
                        if (isProcessedData(specifyTheNodeHandlerTaskQueryInfoList, outgoing.getSourceFlowElement())) {
                            return;
                        }
                        tempUserTask = (UserTask) outgoing.getSourceFlowElement();
                        processSubFlowTaskCandidateSettingsData(specifyTheNodeHandlerTaskQueryInfoList, tempUserTask, processDefinition, task);
                    }
                }
            }
            // 子流程流出数据后续节点处理
            List<SequenceFlow> outgoingFlows = ((FlowNode) flowElement).getOutgoingFlows();
            for (SequenceFlow outgoing : outgoingFlows) {
                // 已处理过的节点不再进行处理（避免死循环）
                if (isProcessedData(specifyTheNodeHandlerTaskQueryInfoList, outgoing.getTargetFlowElement())) {
                    return;
                }
                if (outgoing.getTargetFlowElement() instanceof UserTask) {
                    processFlowTaskCandidateSettingsData(specifyTheNodeHandlerTaskQueryInfoList, outgoing, processDefinition, task);
                }
            }
        }
        // 4.4、当前流程元素没有使用网关
        if (!isFlowGateway) {
            // 已处理过的节点不再进行处理（避免死循环）
            if (isProcessedData(specifyTheNodeHandlerTaskQueryInfoList, flowElement)) {
                return;
            }
            if (flowElement instanceof UserTask) {
                processFlowTaskCandidateSettingsData(specifyTheNodeHandlerTaskQueryInfoList, sequenceFlow, processDefinition, task);
            }
        }
    }

    /**
     * 处理子流程中的用户任务处理人数据
     *
     * @param specifyTheNodeHandlerTaskQueryInfoList
     * @param userTask
     * @param processDefinition
     * @param task
     */
    private void processSubFlowTaskCandidateSettingsData(List<FlowSpecifyTheNodeHandlerTaskQueryInfo> specifyTheNodeHandlerTaskQueryInfoList, UserTask userTask, ProcessDefinition processDefinition, Task task) {
        String fromNodeCode = task.getTaskDefinitionKey();
        if (userTask != null) {
            boolean isExist = false;
            for (FlowSpecifyTheNodeHandlerTaskQueryInfo vo : specifyTheNodeHandlerTaskQueryInfoList) {
                if (vo.getNodeCode().equalsIgnoreCase(userTask.getId())) {
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {
                Map<String, List<CandidateEntity>> candidateMap = new HashMap<>();
                String currentExecutionId = getCurrentExecutionId(task);
                String parentExecutionId = null;
                ExecutionEntity executionEntity = null;
                if (StringUtils.isNotBlank(currentExecutionId)) {
                    executionEntity = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(currentExecutionId).singleResult();
                    if (Objects.nonNull(executionEntity)) {
                        parentExecutionId = executionEntity.getParentId();
                    }
                }
                if (StringUtils.isBlank(parentExecutionId)) {
                    parentExecutionId = task.getProcessInstanceId();
                }

                if (Objects.isNull(executionEntity)) {
                    executionEntity = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(task.getProcessInstanceId()).singleResult();
                }

                String deployId = processDefinition.getDeploymentId();
                String nodeCode = userTask.getId();
                boolean autoGetLastCandidate = false;
                List<ModelCustomConfigDomain> modelCustomConfigDomainList = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(deployId, nodeCode, ConstanceVariable.AUTO_GET_LAST_CANDIDATE);
                if (CollectionUtils.isNotEmpty(modelCustomConfigDomainList)) {
                    if (Objects.equals("1", modelCustomConfigDomainList.get(0).getConfig())) {
                        autoGetLastCandidate = true;
                    }
                }

                FlowSpecifyTheNodeHandlerTaskQueryInfo taskQueryInfo = new FlowSpecifyTheNodeHandlerTaskQueryInfo();
                taskQueryInfo.setNodeCode(userTask.getId());
                taskQueryInfo.setNodeName(userTask.getName());
                taskQueryInfo.setFromNodeCode(fromNodeCode);
                List<ModelNextNodeCandidateSettings> modelNextNodeCandidateSettings = flowNextNodeCandidateRepository.selectByProcessInstanceIdAndNodeCodeAndParentExecutionId(task.getProcessInstanceId(), userTask.getId(), parentExecutionId);
                if (autoGetLastCandidate) {
                    if (CollectionUtils.isNotEmpty(modelNextNodeCandidateSettings)) {
                        getCandidateFromNodeLastCandidateSettings(modelNextNodeCandidateSettings, taskQueryInfo, candidateMap, processDefinition.getDeploymentId(), userTask.getId());
                    } else {
                        getCandidateFromModelTaskCandidateSettings(processDefinition.getDeploymentId(), userTask.getId(), candidateMap, executionEntity, taskQueryInfo, modelNextNodeCandidateSettings);
                    }
                } else {
                    getCandidateFromModelTaskCandidateSettings(processDefinition.getDeploymentId(), userTask.getId(), candidateMap, executionEntity, taskQueryInfo, modelNextNodeCandidateSettings);
                }
                // 是否是会签节点
                taskQueryInfo.setIsMultiTask(FlowUtils.getInstance().isMultiTaskActivity(task.getProcessInstanceId(), userTask.getId()));
                specifyTheNodeHandlerTaskQueryInfoList.add(taskQueryInfo);
            }
        }
    }

    private boolean isProcessedData(List<FlowSpecifyTheNodeHandlerTaskQueryInfo> specifyTheNodeHandlerTaskQueryInfoList, FlowElement flowElement) {
        if (specifyTheNodeHandlerTaskQueryInfoList != null && specifyTheNodeHandlerTaskQueryInfoList.size() > 0) {
            boolean isProcessed = false;
            for (FlowSpecifyTheNodeHandlerTaskQueryInfo vo : specifyTheNodeHandlerTaskQueryInfoList) {
                if (vo.getNodeCode().equalsIgnoreCase(flowElement.getId())) {
                    isProcessed = true;
                    break;
                }
            }
            if (isProcessed) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param nextNodeCandidateTaskDTO 下一节点审批人
     * @return 返回信息
     * @Description 指定下一节点审批人
     * @author liujinjian
     * @date 2021-10-22
     */
    @Override
    public ResponseResult appointNextNodeCandidate(NextNodeCandidateTaskDTO nextNodeCandidateTaskDTO) {
        User user = userRepository.getCurrentUser();

        Task currTask = queryTaskByCandidate(nextNodeCandidateTaskDTO.getTaskId(), user);
        if (Objects.isNull(currTask)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }
        // 设置节点处理人为空的话提示错误消息
        if (nextNodeCandidateTaskDTO.getNodeCandidateTaskDTOList().size() <= 0) {
            return ResponseResult.fail(ErrorCode.EXIST_FORCE_PICK_NODE_NO_PROCESSED.errCode(), ErrorCode.EXIST_FORCE_PICK_NODE_NO_PROCESSED.errMessage());
        }

        try {
            nodeCandidateService.setAssigneeForNode(nextNodeCandidateTaskDTO);
        } catch (Exception e) {
            logger.error("setAssigneeForNode error:", e);
            return ResponseResult.fail(ErrorCode.SET_PARTICIPANTS_FAILED.errCode(), e.getMessage());
        }

        if (StringUtils.isNotBlank(nextNodeCandidateTaskDTO.getComment())) {
            this.addComment(currTask.getId(), user.getUserCode(), currTask.getProcessInstanceId(), CommentTypeEnum.SQ.name(), nextNodeCandidateTaskDTO.getComment());
        }
        return ResponseResult.success();
    }

    /**
     * @param type
     * @param code
     * @param processInstanceId
     * @param userCode
     * @return
     * @Description 根据类型和编码获取当前编码下得人员列表信息
     * @author liujinjian
     * @date 2021-11-01
     */
    @Override
    public FlowTaskCandidateDataTypeVo getChildCandidate(String type, String code, String processInstanceId, String userCode) throws Exception {
        FlowTaskCandidateDataTypeVo typeVo = new FlowTaskCandidateDataTypeVo();
        List<CandidateEntity> candidateInfoVoList = new ArrayList<CandidateEntity>();
        List<UserInfo> dataList = null;
        type = type.toUpperCase();
        typeVo.setDataType(type);
        switch (type) {
            case "ROL":
                dataList = userRoleService.getUserListByRoleId(code);
                if (dataList != null && dataList.size() > 0) {
                    for (UserInfo vo : dataList) {
                        CandidateEntity entity = new CandidateEntity();
                        entity.setCode(vo.getUserCode());
                        entity.setName(vo.getUserName());
                        entity.setType("STA");
                        candidateInfoVoList.add(entity);
                    }
                }
                typeVo.setFlowTaskCandidateInfoVos(candidateInfoVoList);
                break;
            case "ORG":
                // 先获取下面的组织信息列表
                List<OrganizationInfo> organizationInfos = orgAccountService.getOrganizationInfoByParentCode(code).getData();
                if (organizationInfos != null && organizationInfos.size() > 0) {
                    for (OrganizationInfo vo : organizationInfos) {
                        CandidateEntity entity = new CandidateEntity();
                        entity.setCode(vo.getCode());
                        entity.setName(vo.getDisplayName());
                        entity.setType("ORG");
                        candidateInfoVoList.add(entity);
                    }
                }
                // 再获取对应组织下的人员信息列表
                List<UserInfo> userInfoList = userOrgService.getUserListByOrgId(code);
                if (CollectionUtils.isNotEmpty(userInfoList)) {
                    for (UserInfo vo : userInfoList) {
                        CandidateEntity entity = new CandidateEntity();
                        entity.setCode(vo.getUserCode());
                        entity.setName(vo.getUserName());
                        entity.setType("STA");
                        candidateInfoVoList.add(entity);
                    }
                }
                typeVo.setFlowTaskCandidateInfoVos(candidateInfoVoList);
                break;
            case "GROUP":
                dataList = userGroupService.getUserListByGroupId(code, null);
                if (dataList != null && dataList.size() > 0) {
                    for (UserInfo vo : dataList) {
                        CandidateEntity entity = new CandidateEntity();
                        entity.setCode(vo.getUserCode());
                        entity.setName(vo.getUserName());
                        entity.setType("STA");
                        candidateInfoVoList.add(entity);
                    }
                }
                typeVo.setFlowTaskCandidateInfoVos(candidateInfoVoList);
                break;
            case "POSITION":
                dataList = userPositionService.getUserListByPositionId(code);
                if (dataList != null && dataList.size() > 0) {
                    for (UserInfo vo : dataList) {
                        CandidateEntity entity = new CandidateEntity();
                        entity.setCode(vo.getUserCode());
                        entity.setName(vo.getUserName());
                        entity.setType("STA");
                        candidateInfoVoList.add(entity);
                    }
                }
                typeVo.setFlowTaskCandidateInfoVos(candidateInfoVoList);
                break;
            case "FUNCTION":
                // 如果是当前function,当前任务节点处理人为空时,则直接抛异常提示
                if (StringUtils.isBlank(userCode)) {
                    throw new BusiException(ErrorCode.DQR_USER_NOT_EXIST);
                }
                List<CustomFunctionVo> customFunctionVoList = userCustomFunctionService.getCustomFunctionByFunId(code, processInstanceId, userCode);
                if (customFunctionVoList != null && customFunctionVoList.size() > 0) {
                    for (CustomFunctionVo vo : customFunctionVoList) {
                        CandidateEntity entity = new CandidateEntity();
                        entity.setCode(vo.getUserId());
                        entity.setName(vo.getName());
                        entity.setType("STA");
                        candidateInfoVoList.add(entity);
                    }
                }
                typeVo.setFlowTaskCandidateInfoVos(candidateInfoVoList);
                break;
            case "RELATIONSHIP":
                // 只有是拟稿人采取查询组装具体的人员信息,否则,只查询组织列表
                if (Objects.equals(code, CandidateRelationShipEnum.NGR.getCode())) {
                    // 获取人员信息列表
                    Set<UserInfo> userInfoSet = flowCandidateServiceAdapter.handleNextNodeCandidateUsers(type, code, processInstanceId, userCode);
                    // 拟稿人
                    if (CollectionUtils.isNotEmpty(userInfoSet)) {
                        for (UserInfo vo : userInfoSet) {
                            CandidateEntity entity = new CandidateEntity();
                            entity.setCode(vo.getUserCode());
                            entity.setName(vo.getUserName());
                            entity.setType("STA");
                            candidateInfoVoList.add(entity);
                        }
                    }
                }

                // 如果选择的是组织(拟稿人部门或当前人部门),则查询一下组织
                if (Objects.equals(code, CandidateRelationShipEnum.NGRBM.getCode()) ||
                        Objects.equals(code, CandidateRelationShipEnum.DQRBM.getCode())) {
                    // 获取拟稿人
                    String ngrUser = flowCandidateServiceAdapter.getNgrUser(processInstanceId, userCode);

                    // 获取组织信息
                    Map<String, List> shipData = userRelationShipService.getRelationShipList(processInstanceId, code, ngrUser, userCode);
                    List<OrgInfo> tempList = (List<OrgInfo>) shipData.get("data");
                    if (CollectionUtils.isNotEmpty(tempList)) {
                        for (OrgInfo vo : tempList) {
                            CandidateEntity entity = new CandidateEntity();
                            entity.setCode(vo.getOrgCode());
                            entity.setName(vo.getOrgName());
                            entity.setType("ORG");
                            candidateInfoVoList.add(entity);
                        }
                    }
                }
                typeVo.setFlowTaskCandidateInfoVos(candidateInfoVoList);
                break;
            default:
                break;
        }

        return typeVo;
    }

    /**
     * @param specifyTheNodeHandlerTaskQueryInfoList
     * @param outgoingFlow
     * @param processDefinition
     * @return UserTask
     * @Description 处理流程任务候选人设置数据集合
     * @author liujinjian
     * @date 2021-10-21
     */
    private UserTask processFlowTaskCandidateSettingsData(List<FlowSpecifyTheNodeHandlerTaskQueryInfo> specifyTheNodeHandlerTaskQueryInfoList, SequenceFlow outgoingFlow, ProcessDefinition processDefinition, Task task) {
        String fromNodeCode = task.getTaskDefinitionKey();
        UserTask tempUserTask = null;
        if (outgoingFlow.getTargetFlowElement() instanceof UserTask) {
            tempUserTask = (UserTask) outgoingFlow.getTargetFlowElement();
        }
        if (tempUserTask != null) {
            boolean isExist = false;
            for (FlowSpecifyTheNodeHandlerTaskQueryInfo vo : specifyTheNodeHandlerTaskQueryInfoList) {
                if (vo.getNodeCode().equalsIgnoreCase(tempUserTask.getId())) {
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {

                Map<String, List<CandidateEntity>> candidateMap = new HashMap<>();
                String currentExecutionId = getCurrentExecutionId(task);
                String parentExecutionId = null;
                ExecutionEntity executionEntity = null;
                if (StringUtils.isNotBlank(currentExecutionId)) {
                    executionEntity = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(currentExecutionId).singleResult();
                    if (Objects.nonNull(executionEntity)) {
                        parentExecutionId = executionEntity.getParentId();
                    }
                }
                if (StringUtils.isBlank(parentExecutionId)) {
                    parentExecutionId = task.getProcessInstanceId();
                }

                if (Objects.isNull(executionEntity)) {
                    executionEntity = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(task.getProcessInstanceId()).singleResult();
                }

                String deployId = processDefinition.getDeploymentId();
                String nodeCode = tempUserTask.getId();
                boolean autoGetLastCandidate = false;
                List<ModelCustomConfigDomain> modelCustomConfigDomainList = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(deployId, nodeCode, ConstanceVariable.AUTO_GET_LAST_CANDIDATE);
                if (CollectionUtils.isNotEmpty(modelCustomConfigDomainList)) {
                    if (Objects.equals("1", modelCustomConfigDomainList.get(0).getConfig())) {
                        autoGetLastCandidate = true;
                    }
                }

                FlowSpecifyTheNodeHandlerTaskQueryInfo taskQueryInfo = new FlowSpecifyTheNodeHandlerTaskQueryInfo();
                taskQueryInfo.setNodeCode(tempUserTask.getId());
                taskQueryInfo.setNodeName(tempUserTask.getName());
                taskQueryInfo.setFromNodeCode(fromNodeCode);
                List<ModelNextNodeCandidateSettings> modelNextNodeCandidateSettings = flowNextNodeCandidateRepository.selectByProcessInstanceIdAndNodeCodeAndParentExecutionId(task.getProcessInstanceId(), tempUserTask.getId(), parentExecutionId);
                if (autoGetLastCandidate) {
                    if (CollectionUtils.isNotEmpty(modelNextNodeCandidateSettings)) {
                        getCandidateFromNodeLastCandidateSettings(modelNextNodeCandidateSettings, taskQueryInfo, candidateMap, processDefinition.getDeploymentId(), tempUserTask.getId());
                    } else {
                        getCandidateFromModelTaskCandidateSettings(processDefinition.getDeploymentId(), tempUserTask.getId(), candidateMap, executionEntity, taskQueryInfo, modelNextNodeCandidateSettings);
                    }
                } else {
                    getCandidateFromModelTaskCandidateSettings(processDefinition.getDeploymentId(), tempUserTask.getId(), candidateMap, executionEntity, taskQueryInfo, modelNextNodeCandidateSettings);
                }
                // 是否是会签节点
                taskQueryInfo.setIsMultiTask(FlowUtils.getInstance().isMultiTaskActivity(task.getProcessInstanceId(), tempUserTask.getId()));

                specifyTheNodeHandlerTaskQueryInfoList.add(taskQueryInfo);
            }
        }

        for (SequenceFlow flowVo : tempUserTask.getOutgoingFlows()) {
            FlowElement tempFlowElement = flowVo.getTargetFlowElement();
            if (!"end".equalsIgnoreCase(flowVo.getTargetRef())) {
                processSpecifyNodeUserTaskCandidateData(specifyTheNodeHandlerTaskQueryInfoList, processDefinition, flowVo, tempFlowElement, task);
            }
        }

        return tempUserTask;
    }

    private void getCandidateFromNodeLastCandidateSettings(List<ModelNextNodeCandidateSettings> modelNextNodeCandidateSettings
            , FlowSpecifyTheNodeHandlerTaskQueryInfo taskQueryInfo, Map<String, List<CandidateEntity>> candidateMap
            , String deployId, String nodeCode) {
        List<ModelNextNodeCandidateSettingsDomain> nodeCandidateList = null;
        for (ModelNextNodeCandidateSettings modelNextNodeCandidateSetting : modelNextNodeCandidateSettings) {
            CandidateEntity candidateEntity = new CandidateEntity();
            candidateEntity.setCode(modelNextNodeCandidateSetting.getCode());
            candidateEntity.setName(modelNextNodeCandidateSetting.getName());
            candidateEntity.setType(modelNextNodeCandidateSetting.getDataType());
            nodeCandidateList = flowNextNodeCandidateRepository.selectModelCandidateSettingsDomain(modelNextNodeCandidateSetting.getProcessInstanceId(), nodeCode, modelNextNodeCandidateSetting.getDataType(), modelNextNodeCandidateSetting.getCode());
            if (nodeCandidateList != null && nodeCandidateList.size() > 0) {
                candidateEntity.setIsPick("1");
            } else {
                candidateEntity.setIsPick("0");
            }
            addToCandidateMap(candidateEntity, candidateMap);
        }
        if (modelNextNodeCandidateSettings != null && modelNextNodeCandidateSettings.size() > 0) {
            taskQueryInfo.setFromNodeCode(modelNextNodeCandidateSettings.get(0).getFromNodeCode());
        }
        if (MapUtils.isNotEmpty(candidateMap)) {
            List<FlowTaskCandidateDataTypeVo> flowTaskCandidateDataTypeVoList = convertMapToList(candidateMap);
            taskQueryInfo.setDataTypeList(flowTaskCandidateDataTypeVoList);
            taskQueryInfo.setForcePick("0");

            List<ModelCustomConfigDomain> modelCustomConfigDomainList = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(deployId, nodeCode, "forcePick");
            if (CollectionUtils.isNotEmpty(modelCustomConfigDomainList)) {
                if (Objects.equals("1", modelCustomConfigDomainList.get(0).getConfig())) {
                    taskQueryInfo.setForcePick("1");
                }
            }
        }
        nodeCandidateList = flowNextNodeCandidateRepository.selectModelCandidateSettingsDomain(modelNextNodeCandidateSettings.get(0).getProcessInstanceId(), nodeCode, null, null);
        if (nodeCandidateList != null && nodeCandidateList.size() > 0) {
            taskQueryInfo.setIsPick("1");
        }
    }

    private void getCandidateFromModelTaskCandidateSettings(String deployId, String nodeCode, Map<String, List<CandidateEntity>> candidateMap, ExecutionEntity executionEntity, FlowSpecifyTheNodeHandlerTaskQueryInfo taskQueryInfo, List<ModelNextNodeCandidateSettings> modelNextNodeCandidateSettings) {
        // 根据部署ID、节点编码以及类型精准获取是否该节点已经设置
        List<ModelCustomConfig> configs = flowReModelCustomConfigRepository.listModelCustomConfig(deployId, nodeCode, ConstanceVariable.AUTO_GET_LAST_CANDIDATE);
        if (CollectionUtils.isNotEmpty(configs)) {
            // 获取配置信息
            ModelCustomConfig modelCustomConfig = configs.get(0);
            // 检查是否是打开 0：关闭 1：打开
            taskQueryInfo.setIsAutoGetLastCandidate(modelCustomConfig.getConfig());
        }

        ExpressionCmd expressionCmd = null;
        List<ModelNextNodeCandidateSettingsDomain> nodeCandidateList = null;

        //如果节点办理人是留空，则需要将一些信息返回 供前端页面选择
        List<ModelCustomConfigDomain> mccList = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(deployId, nodeCode, ConstanceVariable.CANDIDATE_SET_NULL);
        if (CollectionUtils.isNotEmpty(mccList) && Objects.equals("1", mccList.get(0).getConfig())) {
            taskQueryInfo.setCandidateSetNull("1");
            taskQueryInfo.setNodeCode(nodeCode);
            if (CollectionUtils.isNotEmpty(modelNextNodeCandidateSettings)) {
                taskQueryInfo.setIsPick("1");
            } else {
                taskQueryInfo.setIsPick("0");
            }
            List<ModelCustomConfigDomain> listForce = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(deployId, nodeCode, ConstanceVariable.FORCE_PICK);
            if (CollectionUtils.isNotEmpty(listForce) && Objects.equals("1", listForce.get(0).getConfig())) {
                taskQueryInfo.setForcePick("1");
            } else {
                taskQueryInfo.setForcePick("0");
            }
            //STA
            List<FlowTaskCandidateDataTypeVo> dataList = new ArrayList<>();
            FlowTaskCandidateDataTypeVo voSta = new FlowTaskCandidateDataTypeVo();
            voSta.setDataType("STA");
            dataList.add(voSta);
            //ORG
            FlowTaskCandidateDataTypeVo voOrg = new FlowTaskCandidateDataTypeVo();
            voOrg.setDataType("ORG");
            List<CandidateEntity> orgList = new ArrayList<>();
            List<OrganizationInfo> rootOrganization = orgAccountService.getRootOrg().getData();
            if (CollectionUtils.isNotEmpty(rootOrganization)) {
                for (OrganizationInfo org : rootOrganization) {
                    CandidateEntity can = new CandidateEntity();
                    can.setCode(org.getCode());
                    can.setName(org.getDisplayName());
                    can.setType("ORG");
                    orgList.add(can);
                }
            }

            voOrg.setFlowTaskCandidateInfoVos(orgList);
            dataList.add(voOrg);
            //ROL，默认返回10条
//            List<RoleInfo> roleInfoList = (List<RoleInfo>) userRoleService.getUserRolePageList(null, 1, 10).getDatas();
            FlowTaskCandidateDataTypeVo voRol = new FlowTaskCandidateDataTypeVo();
            voRol.setDataType("ROL");
//            List<CandidateEntity> rolList = new ArrayList<>();
//            for(RoleInfo rol : roleInfoList){
//                CandidateEntity can = new CandidateEntity();
//                can.setCode(rol.getRoleCode());
//                can.setName(rol.getRoleName());
//                can.setType("ROL");
//                rolList.add(can);
//            }
//            voRol.setFlowTaskCandidateInfoVos(rolList);
            dataList.add(voRol);

            //GROUP
//            List<GroupInfo> groupInfoList = (List<GroupInfo>) userGroupService.getUserGroupPageList(null,1,10).getDatas();
            FlowTaskCandidateDataTypeVo voGroup = new FlowTaskCandidateDataTypeVo();
            voGroup.setDataType("GROUP");
//            List<CandidateEntity> groupList = new ArrayList<>();
//            for(GroupInfo groupInfo : groupInfoList){
//                CandidateEntity can = new CandidateEntity();
//                can.setCode(groupInfo.getGroupCode());
//                can.setName(groupInfo.getGroupName());
//                can.setType("GROUP");
//                groupList.add(can);
//            }
//            voGroup.setFlowTaskCandidateInfoVos(groupList);
            dataList.add(voGroup);

            //POSITION
//            List<PositionInfo> positionInfoList = (List<PositionInfo>) userPositionService.getUserPositionPageList(null,1,10).getDatas();
            FlowTaskCandidateDataTypeVo voPos = new FlowTaskCandidateDataTypeVo();
            voPos.setDataType("POSITION");
//            List<CandidateEntity> posList = new ArrayList<>();
//            for(PositionInfo pos : positionInfoList){
//                CandidateEntity can = new CandidateEntity();
//                can.setCode(pos.getPositionCode());
//                can.setName(pos.getPositionName());
//                can.setType("POSITION");
//                posList.add(can);
//            }
//            voPos.setFlowTaskCandidateInfoVos(posList);
            dataList.add(voPos);

            //RELATIONSHIP
            List<UserRelationShip> userRelationShips = userRelationShipService.getUserRelationShipList();
            FlowTaskCandidateDataTypeVo voRel = new FlowTaskCandidateDataTypeVo();
            voRel.setDataType("RELATIONSHIP");
            List<CandidateEntity> relList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(userRelationShips)) {
                for (UserRelationShip rel : userRelationShips) {
                    CandidateEntity can = new CandidateEntity();
                    can.setCode(rel.getShipType());
                    can.setName(rel.getShipName());
                    can.setType("RELATIONSHIP");
                    relList.add(can);
                }
            }

            voRel.setFlowTaskCandidateInfoVos(relList);
            dataList.add(voRel);

            taskQueryInfo.setDataTypeList(dataList);
            return;
        }


        List<ModelTaskCandidateSettings> taskCandidateSettingsList = flowTaskCandidateSettingsRepository.listModelTaskCandidateSettings(deployId, nodeCode);
        for (ModelTaskCandidateSettings taskCandidateSettings : taskCandidateSettingsList) {
            if (taskCandidateSettings.getDataType().equalsIgnoreCase("var")) {
                try {
                    expressionCmd = new ExpressionCmd(taskCandidateSettings.getCandidateValue(), executionEntity);
                    Object objValue = managementService.executeCommand(expressionCmd);
                    if (Objects.nonNull(objValue)) {
                        if (objValue instanceof String) {
                            String strValue = String.valueOf(objValue);
                            String[] str = strValue.split(",");
                            for (String s : str) {
                                CandidateEntity candidateEntity = resolveCandidateService.getCandidateEntity(taskCandidateSettings.getCandidateType(), s);
                                nodeCandidateList = flowNextNodeCandidateRepository.selectModelCandidateSettingsDomain(executionEntity.getProcessInstanceId(), nodeCode, taskCandidateSettings.getCandidateType(), candidateEntity.getCode());
                                if (nodeCandidateList != null && nodeCandidateList.size() > 0) {
                                    candidateEntity.setIsPick("1");
                                } else {
                                    candidateEntity.setIsPick("0");
                                }
                                addToCandidateMap(candidateEntity, candidateMap);
                            }
                        } else if (objValue instanceof List) {
                            List objValueList = (List) objValue;
                            for (Object obj : objValueList) {
                                if (obj instanceof String) {
                                    String str = String.valueOf(obj);
                                    CandidateEntity candidateEntity = resolveCandidateService.getCandidateEntity(taskCandidateSettings.getCandidateType(), str);
                                    nodeCandidateList = flowNextNodeCandidateRepository.selectModelCandidateSettingsDomain(executionEntity.getProcessInstanceId(), nodeCode, taskCandidateSettings.getCandidateType(), candidateEntity.getCode());
                                    if (nodeCandidateList != null && nodeCandidateList.size() > 0) {
                                        candidateEntity.setIsPick("1");
                                    } else {
                                        candidateEntity.setIsPick("0");
                                    }
                                    addToCandidateMap(candidateEntity, candidateMap);
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("getValueFromExpress error:", e);
                }
            } else {
                CandidateEntity candidateEntity = new CandidateEntity();
                candidateEntity.setType(taskCandidateSettings.getCandidateType());
                candidateEntity.setName(taskCandidateSettings.getCandidateName());
                candidateEntity.setCode(taskCandidateSettings.getCandidateValue());
                nodeCandidateList = flowNextNodeCandidateRepository.selectModelCandidateSettingsDomain(executionEntity.getProcessInstanceId(), nodeCode, taskCandidateSettings.getCandidateType(), candidateEntity.getCode());
                if (nodeCandidateList != null && nodeCandidateList.size() > 0) {
                    candidateEntity.setIsPick("1");
                } else {
                    candidateEntity.setIsPick("0");
                }
                addToCandidateMap(candidateEntity, candidateMap);
            }
        }
        if (taskCandidateSettingsList.isEmpty()) {
            List<ModelNextNodeCandidateSettings> modelNextNodeCandidateSettingsList = flowNextNodeCandidateRepository.selectByProcessInstanceIdAndNodeCode(executionEntity.getProcessInstanceId(), nodeCode);
            if (modelNextNodeCandidateSettings != null && modelNextNodeCandidateSettings.size() > 0) {
                for (ModelNextNodeCandidateSettings vo : modelNextNodeCandidateSettingsList) {
                    CandidateEntity candidateEntity = new CandidateEntity();
                    candidateEntity.setType(vo.getDataType());
                    candidateEntity.setName(vo.getName());
                    candidateEntity.setCode(vo.getCode());
                    candidateEntity.setIsPick("1");
                    addToCandidateMap(candidateEntity, candidateMap);
                }
            }
        }

        List<FlowTaskCandidateDataTypeVo> flowTaskCandidateDataTypeVoList = convertMapToList(candidateMap);
        taskQueryInfo.setDataTypeList(flowTaskCandidateDataTypeVoList);


        if (taskCandidateSettingsList != null && taskCandidateSettingsList.size() > 0) {
            taskQueryInfo.setForcePick(taskCandidateSettingsList.get(0).getForcePick());
        }

        if (CollectionUtils.isNotEmpty(modelNextNodeCandidateSettings)) {
            taskQueryInfo.setIsPick("1");
        } else {
            taskQueryInfo.setIsPick("0");
        }

        List<ModelNextNodeCandidateSettings> candidateList = flowNextNodeCandidateRepository.selectByProcessInstanceIdAndNodeCode(executionEntity.getProcessInstanceId(), nodeCode);
        if (candidateList != null && candidateList.size() > 0) {
            taskQueryInfo.setFromNodeCode(candidateList.get(0).getFromNodeCode());
            taskQueryInfo.setIsPick("1");
        }
    }

    private List<FlowTaskCandidateDataTypeVo> convertMapToList(Map<String, List<CandidateEntity>> candidateMap) {
        List<FlowTaskCandidateDataTypeVo> flowTaskCandidateDataTypeVoList = new ArrayList<>();
        if (MapUtils.isNotEmpty(candidateMap)) {
            Iterator<Map.Entry<String, List<CandidateEntity>>> iterator = candidateMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, List<CandidateEntity>> entry = iterator.next();
                String key = entry.getKey();
                List<CandidateEntity> value = entry.getValue();
                FlowTaskCandidateDataTypeVo flowTaskCandidateDataTypeVo = new FlowTaskCandidateDataTypeVo();
                flowTaskCandidateDataTypeVo.setDataType(key);
                flowTaskCandidateDataTypeVo.setFlowTaskCandidateInfoVos(value);
                flowTaskCandidateDataTypeVoList.add(flowTaskCandidateDataTypeVo);
            }
        }
        return flowTaskCandidateDataTypeVoList;

    }

    private void addToCandidateMap(CandidateEntity candidateEntity, Map<String, List<CandidateEntity>> candidateMap) {
        if (Objects.nonNull(candidateEntity)) {
            List<CandidateEntity> flowTaskCandidateInfoVoList = candidateMap.get(candidateEntity.getType());
            if (CollectionUtils.isEmpty(flowTaskCandidateInfoVoList)) {
                flowTaskCandidateInfoVoList = new ArrayList<>();
                candidateMap.put(candidateEntity.getType(), flowTaskCandidateInfoVoList);
            }
            flowTaskCandidateInfoVoList.add(candidateEntity);
        }
    }

    private String getCurrentExecutionId(Task task) {
        String currentExecutionId = task.getExecutionId();
        if (StringUtils.isBlank(currentExecutionId)) {
            String parentTaskId = task.getParentTaskId();
            if (StringUtils.isNotBlank(parentTaskId)) {
                task = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                return getCurrentExecutionId(task);
            }
        }
        return currentExecutionId;
    }

    @Override
    public String getTaskExternalFormUrl(String taskId) {
        String url = null;
        List<Task> taskList = taskService.createTaskQuery().taskId(taskId).list();
        if (Objects.isNull(taskList) || taskList.isEmpty()) {
            return url;
        }
        Task task = taskList.get(0);
        if (Objects.isNull(task.getFormKey())) {
            return url;
        }

        String processDefinitionId = task.getProcessDefinitionId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();

        if (Objects.isNull(processDefinition)) {
            return url;
        }

        List<ModelCustomConfigDomain> modelCustomConfigDomainList = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(processDefinition.getDeploymentId()
                , task.getTaskDefinitionKey(), ConstanceVariable.EXTERNAL_FORM_SHOW_STYLE);
        if (Objects.isNull(modelCustomConfigDomainList) || modelCustomConfigDomainList.isEmpty()) {
            return url;
        }

        String showType = modelCustomConfigDomainList.get(0).getConfig();
        if (Objects.equals(showType, "empty")) {
            String formkey = task.getFormKey();
            FlowFormExternalInfoDomain flowFormExternalInfoDomain = flowFormRepository.findExternalFormInfo(formkey);
            if (Objects.nonNull(flowFormExternalInfoDomain)) {
                String formUrl = flowFormExternalInfoDomain.getFormUrl();
                Map<String, Object> variables = flowFormRepository.getFormVariables(task.getProcessInstanceId(), taskId);
                url = ParseRenderedVariable.parseRenderedVariable(formUrl, variables);
                logger.error("getTaskExternalFormUrl->url=" + url);
                return url;
            }
        }
        return null;

    }

    @Override
    public FlowTaskTraceVo getFlowTaskByTaskIdOrUserCode(String taskId, String userCode) {
        TaskCandidateQueryVo taskCandidateQueryVo = new TaskCandidateQueryVo();
        taskCandidateQueryVo.setTaskId(taskId);

        //如果用户信息不为空，则需要查出来用户信息
        if (StringUtils.isNotBlank(userCode)) {
            userInfoHandleProcessor.convertCandidateQueryVo(taskCandidateQueryVo, userCode);
        }
        FlowTaskTraceVo flowTaskTraceVo = flowTaskTraceRepository.getFlowTaskByTaskIdAndUser(taskCandidateQueryVo);
        return flowTaskTraceVo;
    }

    @Override
    public ResponseResult delegateTaskByHttpRequest(HttpDelegateTaskDto httpDelegateTaskDto) {

        // 任务id
        String taskId = httpDelegateTaskDto.getTaskId();

        // 委派任务的人
        String participantId = httpDelegateTaskDto.getParticipantId();

        // 被委派或指派人
        String delegateUserCode = httpDelegateTaskDto.getDelegateUserCode();

        // 校验字段必填
        if (StringUtils.isBlank(taskId)) {
            return ResponseResult.fail(PARAM_NOT_EXIST.errCode(), "taskId" + PARAM_NOT_EXIST.errMessage());
        }

        // 校验字段必填
        if (StringUtils.isBlank(participantId) || StringUtils.isBlank(delegateUserCode)) {
            return ResponseResult.fail(PARAM_NOT_EXIST.errCode(), "participantId或delegateUserCode" + PARAM_NOT_EXIST.errMessage());
        }

        // 构造委派的vo实体
        TaskDelegateVo taskDelegateVo = new TaskDelegateVo();
        BeanUtils.copyProperties(httpDelegateTaskDto, taskDelegateVo);
        try {
            // 处理委派任务
            return this.delegateTask(taskDelegateVo);
        } catch (Exception ex) {
            logger.error("delegate task fail, fail reason:" + ex.getMessage());
            return ResponseResult.fail(ErrorCode.DELEGATE_TASK_FAIL.errCode(), ErrorCode.DELEGATE_TASK_FAIL.errMessage());
        }
    }

    @Override
    public ResponseResult addSignTaskByHttpRequest(HttpAddSignTaskDto httpAddSignTaskDto) {
        // 加签任务id
        String taskId = httpAddSignTaskDto.getTaskId();

        // 当前任务处理人
        String participantId = httpAddSignTaskDto.getParticipantId();

        // 校验字段必填
        if (StringUtils.isBlank(taskId)) {
            return ResponseResult.fail(ErrorCode.TASK_ID_IS_NULL.errCode(), ErrorCode.TASK_ID_IS_NULL.errMessage() + ":[taskId]");
        }

        // 校验字段必填
        if (StringUtils.isBlank(participantId)) {
            return ResponseResult.fail(ErrorCode.PARTICIPANTID_NOT_EXIST.errCode(), ErrorCode.PARTICIPANTID_NOT_EXIST.errMessage() + ":[participantId]");
        }

        // 构造加签vo实体
        AddSignTaskVo addSignTaskVo = new AddSignTaskVo();
        BeanUtils.copyProperties(httpAddSignTaskDto, addSignTaskVo);
        try {
            // 处理加签任务
            return this.addSignTask(addSignTaskVo);
        } catch (Exception ex) {
            logger.error("add sign task fail, fail reason:" + ex.getMessage());
            return ResponseResult.fail(ErrorCode.ADD_SIGN_TASK_FAIL.errCode(), ErrorCode.ADD_SIGN_TASK_FAIL.errMessage());
        }
    }

    @Override
    public ResponseResult deleteSignTaskByHttpRequest(HttpDeleteSignTaskDto httpDeleteSignTaskDto) {
        // 减签任务id
        String taskId = httpDeleteSignTaskDto.getTaskId();

        // 当前任务处理人
        String participantId = httpDeleteSignTaskDto.getParticipantId();

        // 校验字段必填
        if (StringUtils.isBlank(taskId)) {
            return ResponseResult.fail(ErrorCode.TASK_ID_IS_NULL.errCode(), ErrorCode.TASK_ID_IS_NULL.errMessage() + ":[taskId]");
        }

        // 校验字段必填
        if (StringUtils.isBlank(participantId)) {
            return ResponseResult.fail(ErrorCode.PARTICIPANTID_NOT_EXIST.errCode(), ErrorCode.PARTICIPANTID_NOT_EXIST.errMessage() + ":[participantId]");
        }

        // 构造减签vo实体
        DeleteSignTaskVo deleteSignTaskVo = new DeleteSignTaskVo();
        BeanUtils.copyProperties(httpDeleteSignTaskDto, deleteSignTaskVo);
        try {
            // 处理减签任务
            return this.deleteSignTask(deleteSignTaskVo);
        } catch (Exception ex) {
            logger.error("delete sign task fail, fail reason:" + ex.getMessage());
            return ResponseResult.fail(ErrorCode.DELETE_SIGN_TASK_FAIL.errCode(), ErrorCode.DELETE_SIGN_TASK_FAIL.errMessage());
        }
    }

    private void rollbackToPreNode(String taskId, String comment, String userCode) throws Exception {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        Assert.notNull(task, "根据任务编号找不到任务信息");

        String currentNodeCode = task.getTaskDefinitionKey();

        List<FlowElement> targetFlowElementList = FlowUtils.getInstance().getFirstFrontElement(currentNodeCode, task.getProcessDefinitionId());

        Assert.notEmpty(targetFlowElementList, "回退失败，无法找到回退的目标节点");

        rollbackToTargetNode(task, comment, userCode, targetFlowElementList.get(0).getId());
    }

    private void rollbackToTargetNode(Task task, String comment, String userCode, String targetNode) {
        if (StringUtils.isNotBlank(comment)) {
            this.addComment(task.getId(), userCode, task.getProcessInstanceId(), CommentTypeEnum.BH.getName(), comment);
        }

        String processInstanceId = task.getProcessInstanceId();
        List<Execution> childExecutionList = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).onlyChildExecutions().list();
        List<String> childActivityIdList = childExecutionList.stream().map(Execution::getActivityId).collect(Collectors.toList());

        //1、更新flowTaskTrance表
        childExecutionList.stream().forEach(chilExecution -> {
            Task childTask = taskService.createTaskQuery().executionId(chilExecution.getId()).singleResult();
            if (Objects.nonNull(childTask)) {
                flowTaskTraceRepository.updateStatusToReject(childTask.getId());
            }
        });

        //2、再回退
        runtimeService.createChangeActivityStateBuilder().processInstanceId(task.getProcessInstanceId())
                .moveActivityIdsToSingleActivityId(childActivityIdList, targetNode).changeState();

    }

    /**
     * 根据任务id和用户编码检查任务并更新任务审批trace信息
     *
     * @param taskId
     * @param user
     * @return
     */
    public CheckResult checkAssigneeByTaskIdAndUser(String taskId, User user) {
        // 如果传的user为空,则返回检查结果用户不存在
        if (Objects.isNull(user)) {
            return CheckResult.fail(ErrorCode.USER_NOT_EXIST.errCode(), ErrorCode.USER_NOT_EXIST.errMessage());
        }

        // 按照候选人方式检查任务是否存在
        Task task = flowBaseDataHandleProcessor.getTaskByCandidate(taskId, user.getUserCode());
        if (Objects.isNull(task)) {
            return CheckResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }

        // 根据流程实例ID获取流程实例
        ProcessInstance processInstance = flowBaseDataHandleProcessor.resolveProcessInstance(task.getProcessInstanceId());
        if (Objects.isNull(processInstance)) {
            logger.warn("流程实例不存在");
            return CheckResult.fail(ErrorCode.PROCESS_INSTANCE_NOT_EXIST.errCode(), ErrorCode.PROCESS_INSTANCE_NOT_EXIST.errMessage());
        }

        // 判断流程实例当前状态
        if (processInstance.isSuspended()) {
            logger.warn("流程已挂起");
            return CheckResult.fail(ErrorCode.PROCESS_SUSPEND_ERROR.errCode(), ErrorCode.PROCESS_SUSPEND_ERROR.errMessage());
        }

        // 如果未设置审批人，则优先设置审批人
        // 相当于把签收的动作合并在处理中了
        if (StringUtils.isBlank(task.getAssignee())) {
            //1.先签收
            taskService.claim(task.getId(), user.getUserCode());
            //2.给操作记录赋值
            FlowTaskTrace flowTaskTrace = new FlowTaskTrace();
            flowTaskTrace.setOperator(user.getUserName());
            flowTaskTrace.setOperatorCode(user.getUserCode());
            flowTaskTrace.setUpdateTime(new Date());
            flowTaskTrace.setTaskId(taskId);
            flowTaskTrace.setProcessInstanceId(task.getProcessInstanceId());
            flowTaskTraceDAO.updateByTaskIdAndProcId(flowTaskTrace);
        }
        return CheckResult.success();
    }


    /**
     * @param processInstanceId
     * @param nodeCode
     * @return
     * @Description 根据实例ID和节点编码获取当前节点候选人对象
     * @author liujinjian
     * @date 2021-11-11
     */
    @Override
    public FlowSpecifyTheNodeHandlerTaskQueryInfo getCurrentNodeCandidateInfo(String processInstanceId, String nodeCode) throws Exception {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(processInstance)) {
            throw new Exception(String.format("根据流程实例编号[%s]未找到正在运行的流程", processInstanceId));
        }
        ExecutionEntity executionEntity = (ExecutionEntity) runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult();
        FlowSpecifyTheNodeHandlerTaskQueryInfo dataInfo = new FlowSpecifyTheNodeHandlerTaskQueryInfo();

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
        if (Objects.nonNull(processDefinition)) {
            Map<String, List<CandidateEntity>> candidateMap = new HashMap<>();
            List<ModelNextNodeCandidateSettings> modelNextNodeCandidateSettings = null;
            if (StringUtils.isNotBlank(nodeCode)) {
                modelNextNodeCandidateSettings = flowNextNodeCandidateRepository.selectByProcessInstanceIdAndNodeCodeAndParentExecutionId(processInstanceId
                        , nodeCode, processInstanceId);
            }
            getCandidateFromModelTaskCandidateSettings(processDefinition.getDeploymentId(), nodeCode, candidateMap, executionEntity, dataInfo, modelNextNodeCandidateSettings);
        }
        return dataInfo;

    }

    @Override
    public String mustExpress(String taskId) {

        Assert.notNull(taskId, "taskId不能为空");

        //任务可能已完成，只能查flow_task_trace
        FlowTaskTraceVo flowTaskTraceVo = flowTaskTraceRepository.getTaskTraceByTaskId(taskId);
        String processInstanceId = null;
        String nodeCode = null;

        //加签之后，会把主的flow_Task_trace给删除掉，对应的act_ru_task会保留
        //所以这个地方再单独判断一下act_ru_task
        if (Objects.isNull(flowTaskTraceVo)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            Assert.notNull(task, String.format("根据任务id[%s]未找到任务", taskId));
            processInstanceId = task.getProcessInstanceId();
            nodeCode = task.getTaskDefinitionKey();
        } else {
            processInstanceId = flowTaskTraceVo.getProcessInstanceId();
            nodeCode = flowTaskTraceVo.getActivityId();
        }


        FlowProcessInstanceTraceVo flowProcessInstanceTraceVo = flowProcessInstanceTraceRepository.getProcessInstanceTraceByProcessInstanceId(processInstanceId);

        if (Objects.nonNull(flowProcessInstanceTraceVo)) {
            String processDefinitionId = flowProcessInstanceTraceVo.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();

            Assert.notNull(processDefinition, String.format("根据流程定义id[%s]未找到流程定义", processDefinitionId));

            String deployId = processDefinition.getDeploymentId();

            List<ModelCustomConfigDomain> modelCustomConfigDomainList = flowReModelCustomConfigRepository.listModelConfigByDeployIdAndType(deployId, nodeCode, ConstanceVariable.MUST_EXPRESS);
            if (CollectionUtils.isNotEmpty(modelCustomConfigDomainList)) {
                return modelCustomConfigDomainList.get(0).getConfig();
            }
        }

        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult takeBack(HttpTaskTakeBackDto taskTakeBackDto) {

        //查看节点是否有‘拿回’权限
        //获取流程节点权限列表
        FlowTaskTraceVo flowTaskTraceVo = taskTraceService.getTaskTraceByTaskId(taskTakeBackDto.getTaskId());
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(flowTaskTraceVo.getProcessInstanceId()).singleResult();
        String processDefinitionId = processInstance.getProcessDefinitionId();

        List<FlowReNodeAuthVo> nodeAuthList = nodeAuthService.listNodeAuthByProcdefIdAndNodeCode(processDefinitionId, flowTaskTraceVo.getActivityId());
        List<FlowReNodeAuthVo> takeBackList = nodeAuthList.stream().filter(o -> o.getAuthName().equals("takeBack")).collect(Collectors.toList());
        if (takeBackList == null || takeBackList.size() == 0) {
            return ResponseResult.fail(ErrorCode.TASK_TAKEBACK_FAILED.errCode(), ErrorCode.TASK_TAKEBACK_FAILED.errMessage() + ": 当前流程节点无‘拿回’权限");
        }

        //当前流程实例的所有待办任务，也是下一节点(非网关节点)的任务
        List<Task> todoTasks = taskService.createTaskQuery().processInstanceId(flowTaskTraceVo.getProcessInstanceId()).list();

        Set<String> nodeCodeSet = todoTasks.stream().map(o -> o.getTaskDefinitionKey()).collect(Collectors.toSet());

        //当前节点已是待办，不能拿回
        if (nodeCodeSet.contains(flowTaskTraceVo.getActivityId())) {
            return ResponseResult.fail(ErrorCode.TASK_TAKEBACK_FAILED.errCode(), ErrorCode.TASK_TAKEBACK_FAILED.errMessage() + ": 正在运行的节点与当前节点为同一节点[" + flowTaskTraceVo.getTaskName() + "]，不能拿回");
        }

        if (nodeCodeSet.size() > 1) {
            return ResponseResult.fail(ErrorCode.TASK_TAKEBACK_FAILED.errCode(), ErrorCode.TASK_TAKEBACK_FAILED.errMessage() + ": 存在多个正在运行的任务，不能拿回");
        }


        FlowTaskTraceVo multiTaskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(todoTasks.get(0).getId());
        if (Objects.nonNull(multiTaskTrace)) {
            FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
            flowTaskTraceExample.createCriteria().andParentIdEqualTo(multiTaskTrace.getParentId()).andLinkStatusEqualTo(TaskLinkStatusEnum.DONE.getCode());
            List<FlowTaskTrace> flowTaskTraces = flowTaskTraceDAO.selectByExample(flowTaskTraceExample);
            if (CollectionUtils.isNotEmpty(flowTaskTraces)) {
                return ResponseResult.fail(ErrorCode.TASK_TAKEBACK_FAILED.errCode(), ErrorCode.TASK_TAKEBACK_FAILED.errMessage() + ": 已有任务被处理，不能拿回");
            }
        }

        //这些任务是否都是未读的
        List<String> todoTaskIds = todoTasks.stream().map(o -> o.getId()).collect(Collectors.toList());

        int count = flowTaskInstApproverRepository.countReadedTask(todoTaskIds);
        if (count > 0) {
            return ResponseResult.fail(ErrorCode.TASK_TAKEBACK_FAILED.errCode(), ErrorCode.TASK_TAKEBACK_FAILED.errMessage() + ": 下一节点任务有已读不能拿回");
        } else {
            //拿回, 根据一个待办任务回退到上一节点
            try {
                //预处理
                this.executeNodeOperEvent(taskTakeBackDto.getTaskId()
                        , taskTakeBackDto.getUserCode(), NodeOperEnum.TAKE_BACK, NodeOperEventTypeEnum.BEFORE);

                rollbackService.takeBack(todoTaskIds.get(0), taskTakeBackDto.getComment(), taskTakeBackDto.getUserCode());
                //回退后，根据todoTaskIds，把flow_task_trace中的记录都删掉，把之前的待办任务轨迹删掉
                todoTaskIds.forEach(todoTaskId -> {
                    FlowTaskTraceExample flowTaskTraceExample = new FlowTaskTraceExample();
                    flowTaskTraceExample.createCriteria().andTaskIdEqualTo(todoTaskId).andProcessInstanceIdEqualTo(flowTaskTraceVo.getProcessInstanceId());
                    flowTaskTraceDAO.deleteByExample(flowTaskTraceExample);

                });
                //后处理
                this.executeNodeOperEvent(taskTakeBackDto.getTaskId()
                        , taskTakeBackDto.getUserCode(), NodeOperEnum.TAKE_BACK, NodeOperEventTypeEnum.AFTER);

            } catch (Exception e) {
                logger.error("execute takeback error:", e);
                return ResponseResult.fail(ErrorCode.TASK_TAKEBACK_FAILED.errCode(), ErrorCode.TASK_TAKEBACK_FAILED.errMessage() + ": " + e.getMessage());
            }

            // 拿回成功之后,删除任务同步任务外围
            this.syncTaskStatus(todoTaskIds);
            return ResponseResult.success();
        }

    }

    @Override
    public List<ModelNextNodeCandidateSettings> getLastCandidate(String taskId, String nodeCode) {
        String processInstanceId = "";
        // 获取流程实例ID,查询不到,再查询历史
        FlowTaskTraceVo flowTaskTrace = flowTaskTraceRepository.getTaskTraceByTaskId(taskId);
        if (Objects.nonNull(flowTaskTrace)) {
            processInstanceId = flowTaskTrace.getProcessInstanceId();
        } else {
            HistoricTaskInstance historyTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
            if (Objects.nonNull(historyTask)) {
                processInstanceId = historyTask.getProcessInstanceId();
            }
        }
        if (StringUtils.isBlank(processInstanceId)) {
            return Collections.emptyList();
        }

        // 根据流程实例ID和节点编码获取之前设置的后续节点候选人
        return flowNextNodeCandidateRepository.selectByProcessInstanceIdAndNodeCode(processInstanceId, nodeCode);
    }

    /**
     * 根据流程实例ID获取对应设置的候选人列表详情信息
     *
     * @param processInstanceId
     * @return
     */
    @Override
    public List<NodeCandidateUsersSetting> getAllLastCandidate(String processInstanceId) {
        if (StringUtils.isBlank(processInstanceId)) {
            return Collections.emptyList();
        }

        // 根据流程实例ID获取之前设置的后续节点候选人
        List<ModelNextNodeCandidateSettings> settingsList = flowNextNodeCandidateRepository.selectByProcessInstanceId(processInstanceId);
        if (CollectionUtils.isEmpty(settingsList)) {
            return Collections.emptyList();
        }

        // 存储节点并且是不重复的
        Set<String> nodes = new HashSet<>();

        // 按照节点编码作为key进行数据分组
        Map<String, List<NodeCandidateUsersSettingDetail>> dataMap = new HashMap<>();

        // 循环遍历组装
        for (ModelNextNodeCandidateSettings candidateSetting : settingsList) {
            NodeCandidateUsersSetting setting = new NodeCandidateUsersSetting();
            // 校验是否包含节点编码,如果包含,则认为是重复的,则取出并累加,否则,直接创建集合并添加数据
            if (!nodes.contains(candidateSetting.getNodeCode())) {
                nodes.add(candidateSetting.getNodeCode());
                // 存储每个节点设置的候选人列表数据明细
                List<NodeCandidateUsersSettingDetail> settingDetailList = new ArrayList<>();
                setting.setNodeCode(candidateSetting.getNodeCode());
                NodeCandidateUsersSettingDetail settingDetail = new NodeCandidateUsersSettingDetail();
                settingDetail.setDataType(candidateSetting.getDataType());
                settingDetail.setCode(candidateSetting.getCode());
                settingDetail.setName(candidateSetting.getName());
                settingDetail.setFromNodeCode(candidateSetting.getFromNodeCode());
                settingDetail.setId(candidateSetting.getId());
                settingDetail.setParentExecutionId(candidateSetting.getParentExecutionId());
                settingDetail.setProcessInstanceId(candidateSetting.getProcessInstanceId());
                settingDetail.setTaskId(candidateSetting.getTaskId());
                settingDetailList.add(settingDetail);
                dataMap.put(candidateSetting.getNodeCode(), settingDetailList);
            } else {
                NodeCandidateUsersSettingDetail settingDetail = new NodeCandidateUsersSettingDetail();
                settingDetail.setDataType(candidateSetting.getDataType());
                settingDetail.setCode(candidateSetting.getCode());
                settingDetail.setName(candidateSetting.getName());
                settingDetail.setFromNodeCode(candidateSetting.getFromNodeCode());
                settingDetail.setId(candidateSetting.getId());
                settingDetail.setParentExecutionId(candidateSetting.getParentExecutionId());
                settingDetail.setProcessInstanceId(candidateSetting.getProcessInstanceId());
                settingDetail.setTaskId(candidateSetting.getTaskId());
                List<NodeCandidateUsersSettingDetail> dataList = dataMap.get(candidateSetting.getNodeCode());
                if (CollectionUtils.isNotEmpty(dataList)) {
                    dataList.add(settingDetail);
                }
            }
        }

        // 存储按照节点编码进行分组的数据集合
        List<NodeCandidateUsersSetting> settings = new ArrayList<>();

        // 按照key进行循环遍历组装
        Set<Map.Entry<String, List<NodeCandidateUsersSettingDetail>>> entrySets = dataMap.entrySet();
        for (Map.Entry<String, List<NodeCandidateUsersSettingDetail>> entry : entrySets) {
            NodeCandidateUsersSetting candidateUsersSetting = new NodeCandidateUsersSetting();
            candidateUsersSetting.setNodeCode(entry.getKey());
            candidateUsersSetting.setNodeCandidateUsersList(entry.getValue());
            settings.add(candidateUsersSetting);
        }
        return settings;
    }

    /**
     * 获取指定节点最新设置的候选人或者最近审批人信息
     *
     * @param processInstanceId
     * @param nodeCode
     * @return
     */
    @Override
    public ResponseResult getLastCandidateOrOperator(String processInstanceId, String nodeCode) {
        if (StringUtils.isBlank(processInstanceId)) {
            return ResponseResult.fail(ErrorCode.PARAM_NOT_EXIST.errCode(), ErrorCode.PARAM_NOT_EXIST.errMessage());
        }
        //根据流程id，查询每个节点最近的审批信息（驳回多次，只取最新一次审批结果）
        List<FlowTaskTraceVo> taskRecords = flowTaskTraceRepository.getAllLastTaskRecords(processInstanceId);
        //会签节点存在多条审批记录，根据parent_id将其添加进审批记录集合
        // 筛选审批记录中parent_id不为空的记录,根据parent_id查询会签节点审批记录
        List<FlowTaskTraceVo> multiTaskRecords = CollectionUtils.isEmpty(taskRecords) ? null : taskRecords.stream().filter(t -> StringUtils.isNotEmpty(t.getParentId())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(multiTaskRecords)) {
            for (FlowTaskTraceVo flowTaskTraceVo : multiTaskRecords) {
                taskRecords.addAll(flowTaskTraceRepository.getTaskTraceByParentId(flowTaskTraceVo.getParentId()));
            }
        }

        // 根据流程实例ID获取之前设置的后续节点候选人
        List<ModelNextNodeCandidateSettings> settingsList = flowNextNodeCandidateRepository.selectByProcessInstanceId(processInstanceId);

        // 存储节点并且是不重复的
        Set<String> nodes = new HashSet<>();

        // 按照节点编码作为key进行数据分组
        Map<String, List<NodeCandidateUsersSettingDetail>> dataMap = new HashMap<>();

        // 循环遍历预指派信息列表，组装
        if (!CollectionUtils.isEmpty(settingsList)) {
            for (ModelNextNodeCandidateSettings candidateSetting : settingsList) {
                // 校验是否包含节点编码,如果包含,则认为是重复的,则取出并累加,否则,直接创建集合并添加数据
                if (!nodes.contains(candidateSetting.getNodeCode())) {
                    nodes.add(candidateSetting.getNodeCode());
                    dataMap.put(candidateSetting.getNodeCode(), buildCandidateUsersSettingDetail(candidateSetting));
                } else {
                    List<NodeCandidateUsersSettingDetail> dataList = dataMap.get(candidateSetting.getNodeCode());
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        dataList.addAll(buildCandidateUsersSettingDetail(candidateSetting));
                    }
                }
            }
        }

        // 记录被添加进nodes集合的审批节点id
        List<String> historyNodes = new ArrayList<>();
        // 循环遍历审批历史信息列表，组装
        if (!CollectionUtils.isEmpty(taskRecords)) {
            //去重
            taskRecords = taskRecords.stream().distinct().collect(Collectors.toList());
            for (FlowTaskTraceVo flowTaskTraceVo : taskRecords) {
                // 校验预指派是否包含节点编码,如果包含,则认为已存在指派信息，不作处理,否则,直接添加历史审批记录的节点审批人信息
                if (!nodes.contains(flowTaskTraceVo.getActivityId())) {
                    nodes.add(flowTaskTraceVo.getActivityId());
                    historyNodes.add(flowTaskTraceVo.getActivityId());
                    dataMap.put(flowTaskTraceVo.getActivityId(), buildCandidateUsersSettingDetail(flowTaskTraceVo));
                } else if (historyNodes.contains(flowTaskTraceVo.getActivityId())) {
                    List<NodeCandidateUsersSettingDetail> dataList = dataMap.get(flowTaskTraceVo.getActivityId());
                    if (CollectionUtils.isNotEmpty(dataList)) {
                        dataList.addAll(buildCandidateUsersSettingDetail(flowTaskTraceVo));
                    }
                }
            }
        }

        // 按照节点编码排序
        Map<String, List<NodeCandidateUsersSettingDetail>> sortedMap = dataMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).
                collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));

        Set<Map.Entry<String, List<NodeCandidateUsersSettingDetail>>> entrySets = sortedMap.entrySet();

        if (!StringUtils.isBlank(nodeCode)) {
            for (Map.Entry<String, List<NodeCandidateUsersSettingDetail>> entry : entrySets) {
                if (entry.getKey().equals(nodeCode)) {
                    return ResponseResult.success(entry);
                }
            }
        }


        return ResponseResult.success(entrySets);
    }

    @Override
    public ResponseResult batchTurnTasks(BatchTurnTaskVo batchTurnTaskVo) {

        // 被转办的人员不能为空
        String turnToUserCode = batchTurnTaskVo.getTurnToUserCode();
        if (StringUtils.isBlank(turnToUserCode)) {
            return ResponseResult.fail(ErrorCode.PARAM_NOT_EXIST.errCode(), ErrorCode.PARAM_NOT_EXIST.errMessage());
        }

        // 批量获取需要转办的任务ID集合
        List<String> taskIds = batchTurnTaskVo.getTaskIds();
        if (CollectionUtils.isEmpty(taskIds)) {
            return ResponseResult.fail(ErrorCode.PARAM_NOT_EXIST.errCode(), ErrorCode.PARAM_NOT_EXIST.errMessage());
        }

        // 先校验批量的待办任务是否是转给了自己
        User user = userRepository.getCurrentUser();
        if (Objects.equals(user.getUserCode(), batchTurnTaskVo.getTurnToUserCode())) {
            return ResponseResult.fail(ErrorCode.CAN_NOT_ASSIGN_SELF.errCode(), ErrorCode.CAN_NOT_ASSIGN_SELF.errMessage());
        }

        // 循环处理
        for (String taskId : taskIds) {
            try {
                if (StringUtils.isEmpty(batchTurnTaskVo.getUserCode())) {
                    List<FlowExecutionQueryLink> list = flowExecutionQueryDAO.queryIdentityLinkByTaskId(taskId).stream().filter(link -> "STA".equals(link.getType())).collect(Collectors.toList());
                    List<FlowExecutionQueryLink> flowExecutionQueryLink = list.stream().filter(link -> user.getUserCode().equals(link.getUserId())).collect(Collectors.toList());
                    if (flowExecutionQueryLink.isEmpty() && !list.isEmpty()) {
                        batchTurnTaskVo.setUserCode(list.get(0).getUserId());
                    } else {
                        batchTurnTaskVo.setUserCode(user.getUserCode());
                    }
                }
                // 获取任务
                Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
                TurnTaskVo turnTaskVo = new TurnTaskVo();
                turnTaskVo.setUserCode(batchTurnTaskVo.getUserCode());
                turnTaskVo.setTaskId(taskId);
                turnTaskVo.setTurnToUserCode(batchTurnTaskVo.getTurnToUserCode());
                flowTurnTaskService.turnTask(task, turnTaskVo);
            } catch (Exception ex) {
                ex.printStackTrace();
                logger.info("转办任务失败：" + ex.getMessage() + ",任务ID：" + taskId);
            }
        }
        return ResponseResult.success("批量转办成功");
    }

    private void syncDataByScene(String taskId, String taskStatus) {
        List<String> taskIds = new ArrayList<>();
        taskIds.add(taskId);
        syncProcessTaskProcessor.syncDataByScene(null, taskIds, null, taskStatus);
    }

    /**
     * 同步节点待办任务状态
     *
     * @param taskIds
     */
    private void syncTaskStatus(List<String> taskIds) {
        syncProcessTaskProcessor.deleteTask(taskIds);
    }

    private List<NodeCandidateUsersSettingDetail> buildCandidateUsersSettingDetail(ModelNextNodeCandidateSettings candidateSetting) {
        List<NodeCandidateUsersSettingDetail> settingDetailList = new ArrayList<>();
        NodeCandidateUsersSettingDetail settingDetail = new NodeCandidateUsersSettingDetail();
        settingDetail.setDataType(candidateSetting.getDataType());
        settingDetail.setCode(candidateSetting.getCode());
        if (CandidateTypeEnum.STA.getCode().equals(candidateSetting.getDataType())) {
            settingDetail.setEmployeeCode(userService.getEmployeeCodeById(candidateSetting.getCode()));
        }
        settingDetail.setName(candidateSetting.getName());
        settingDetail.setFromNodeCode(candidateSetting.getFromNodeCode());
        settingDetail.setId(candidateSetting.getId());
        settingDetail.setParentExecutionId(candidateSetting.getParentExecutionId());
        settingDetail.setProcessInstanceId(candidateSetting.getProcessInstanceId());
        settingDetail.setTaskId(candidateSetting.getTaskId());
        settingDetailList.add(settingDetail);
        return settingDetailList;
    }

    private List<NodeCandidateUsersSettingDetail> buildCandidateUsersSettingDetail(FlowTaskTraceVo flowTaskTraceVo) {
        // 存储每个节点设置的历史审批列表数据明细
        List<NodeCandidateUsersSettingDetail> settingDetailList = new ArrayList<>();
        NodeCandidateUsersSettingDetail settingDetail = new NodeCandidateUsersSettingDetail();
        settingDetail.setDataType(CandidateTypeEnum.STA.getCode());
        settingDetail.setCode(flowTaskTraceVo.getOperatorCode());
        settingDetail.setEmployeeCode(userService.getEmployeeCodeById(flowTaskTraceVo.getOperatorCode()));
        settingDetail.setName(flowTaskTraceVo.getOperator());
        settingDetail.setFromNodeCode(flowTaskTraceVo.getActivityId());
        settingDetail.setParentExecutionId("");
        settingDetail.setProcessInstanceId(flowTaskTraceVo.getProcessInstanceId());
        settingDetail.setTaskId(flowTaskTraceVo.getTaskId());
        settingDetailList.add(settingDetail);
        return settingDetailList;
    }

    /**
     * 更新待办中的【计划完成时间】
     *
     * @param httpUpdateCompTimeDto 工作项id等信息
     * @return 处理结果
     */
    @Override
    public ResponseResult updateTaskCompTime(HttpUpdateCompTimeDto httpUpdateCompTimeDto) {
        FlowTaskTraceVo currTask = flowTaskTraceRepository.getTaskTraceByTaskId(httpUpdateCompTimeDto.getTaskId());
        if (Objects.isNull(currTask)) {
            return ResponseResult.fail(ErrorCode.TASK_NOT_EXIST.errCode(), ErrorCode.TASK_NOT_EXIST.errMessage());
        }
        return syncTaskTracePostProcessor.syncUpdateTaskCompTime(httpUpdateCompTimeDto.getTaskId(), httpUpdateCompTimeDto.getNewCompTime());
    }

    /**
     * 获取流程实例当前任务信息
     *
     * @param processInstanceId 流程实例id
     * @return 当前节点信息
     */
    @Override
    public ResponseResult getCurrentTaskInfo(String processInstanceId) {
        if (StringUtils.isBlank(processInstanceId)) {
            return ResponseResult.fail(ErrorCode.PARAM_NOT_EXIST.errCode(), "processInstanceId不能都为空!");
        }
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(processInstance)) {
            return ResponseResult.fail(ErrorCode.DATA_EXIST.errCode(), String.format("根据流程实例编号[%s]未找到正在运行的流程！", processInstanceId));
        }
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        if (CollectionUtils.isEmpty(tasks)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "根据流程实例编号[%s]未找到正在运行的任务！");
        }

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
        List<String> firstUserTaskIds = new ArrayList<>();
        if (Objects.nonNull(processDefinition)) {
            List<UserTask> firstTasks = FlowUtils.getInstance().getFirstTasks(processDefinition.getId());
            firstUserTaskIds = firstTasks.stream().map(UserTask::getId).collect(Collectors.toList());
        }
        List<TaskDTO> resultTasks = new ArrayList<>();
        for (int i = 0; i < tasks.size(); i++) {
            Task task = tasks.get(i);
            TaskDTO taskDTO = new TaskDTO();
            taskDTO.setTaskId(task.getId());
            taskDTO.setActivityId(task.getTaskDefinitionKey());
            taskDTO.setIsFirstTask(firstUserTaskIds.contains(taskDTO.getActivityId()));
            List<FlowTaskInstApproverVo> approverVos = flowTaskInstApproverRepository.selectListByTaskId(task.getId());
            List<Object> approverList = new ArrayList<>(approverVos.size());
            approverVos.forEach(approverVo -> {
                Map<String, String> approver = new HashMap<>();
                approver.put("userId", approverVo.getUserId());
                approver.put("userName", approverVo.getUserName());
                approverList.add(approver);
            });
            taskDTO.setOperators(approverList);
            resultTasks.add(taskDTO);
        }
        return ResponseResult.success(resultTasks);
    }

    @Override
    public void flowDirector(JSONObject requsetParam) {
        try {
            String taskId = requsetParam.getString("workItemId");
            taskId = StringUtils.isNotEmpty(taskId) ? taskId : requsetParam.getString("taskId");
            if (StringUtils.isEmpty(taskId)) {
                return;
            }
            String deploymentId = requsetParam.getString("deploymentId");
            if (StringUtils.isNotEmpty(deploymentId)) {
                doProcess(deploymentId, taskId);
            } else {
                Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
                deploymentId = runtimeService.createProcessInstanceQuery().processDefinitionId(task.getProcessDefinitionId())
                        .singleResult().getDeploymentId();
                doProcess(deploymentId, taskId);
            }
        } catch (Exception ignored) {
        }
    }

    private void doProcess(String deploymentId, String taskId) {
        List<ModelCustomConfigDomain> configDomains = flowReModelCustomConfigRepository.listModelConfigByParams(deploymentId, null, ConstanceVariable.OWNER_CODE);
        if (configDomains.size() == 1) {
            ModelCustomConfigDomain modelCustomConfigDomain = configDomains.get(0);
            String config = modelCustomConfigDomain.getConfig();
            List<UserInfo> userInfoList = userService.getUserListByEmployeeCodeList(Collections.singletonList(config));
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            HttpDispatchWorkItemDto dispatchWorkItemDto = new HttpDispatchWorkItemDto();
            dispatchWorkItemDto.setWorkItemId(taskId);
            dispatchWorkItemDto.setComment("流程出错转为流程负责人处理");
            dispatchWorkItemDto.setParticipantId(task.getOwner());
            dispatchWorkItemDto.setTurnToUserCode(userInfoList.get(0).getUserCode());
            flowTurnTaskService.turnTask(dispatchWorkItemDto);

        }
    }

    /**
     * 批量同步待办任务至待办组件
     *
     * @param tasksManagerDTOS
     * @return
     */
    @Override
    public ResponseResult batchInsertToTasksManager(HttpTaskManagerBatchDto tasksManagerDTOS) {
        ResponseResult<String> responseResult = ResponseResult.success();

        return responseResult;
    }

    protected List<IdentityLinkEntity> convertToIdentityLinkEntitys(List<IdentityLink> identityLinks) {
        List<IdentityLinkEntity> identityLinkObjects = new ArrayList<>();
        for (IdentityLink identityLink : identityLinks) {
            identityLinkObjects.add((IdentityLinkEntity) identityLink);
        }
        return identityLinkObjects;
    }


}
